blob: 75d94bd91ce38c9a6ccd73bf2c42d54b535f0bc7 [file] [log] [blame]
Greg Claytone996fd32011-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
Greg Clayton4116e932012-05-15 02:33:01 +000016#include "lldb/Breakpoint/BreakpointIDList.h"
Greg Claytone996fd32011-03-08 22:40:15 +000017#include "lldb/Core/Error.h"
Greg Clayton8b82f082011-04-12 05:54:46 +000018#include "lldb/Core/Log.h"
Greg Clayton1f746072012-08-29 21:13:06 +000019#include "lldb/Core/ModuleSpec.h"
Greg Claytone996fd32011-03-08 22:40:15 +000020#include "lldb/Core/PluginManager.h"
21#include "lldb/Host/FileSpec.h"
Greg Claytonded470d2011-03-19 01:12:21 +000022#include "lldb/Host/Host.h"
Greg Clayton8b82f082011-04-12 05:54:46 +000023#include "lldb/Target/Process.h"
Greg Claytone996fd32011-03-08 22:40:15 +000024#include "lldb/Target/Target.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000025#include "lldb/Utility/Utils.h"
Greg Claytone996fd32011-03-08 22:40:15 +000026
27using namespace lldb;
28using namespace lldb_private;
29
30// Use a singleton function for g_local_platform_sp to avoid init
31// constructors since LLDB is often part of a shared library
32static PlatformSP&
33GetDefaultPlatformSP ()
34{
35 static PlatformSP g_default_platform_sp;
36 return g_default_platform_sp;
37}
38
Greg Claytone996fd32011-03-08 22:40:15 +000039static Mutex &
40GetConnectedPlatformListMutex ()
41{
42 static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
43 return g_remote_connected_platforms_mutex;
44}
45static std::vector<PlatformSP> &
46GetConnectedPlatformList ()
47{
48 static std::vector<PlatformSP> g_remote_connected_platforms;
49 return g_remote_connected_platforms;
50}
51
Greg Claytonab65b342011-04-13 22:47:15 +000052
53const char *
54Platform::GetHostPlatformName ()
55{
56 return "host";
57}
58
Greg Claytone996fd32011-03-08 22:40:15 +000059//------------------------------------------------------------------
60/// Get the native host platform plug-in.
61///
62/// There should only be one of these for each host that LLDB runs
63/// upon that should be statically compiled in and registered using
64/// preprocessor macros or other similar build mechanisms.
65///
66/// This platform will be used as the default platform when launching
67/// or attaching to processes unless another platform is specified.
68//------------------------------------------------------------------
69PlatformSP
70Platform::GetDefaultPlatform ()
71{
72 return GetDefaultPlatformSP ();
73}
74
75void
76Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
77{
78 // The native platform should use its static void Platform::Initialize()
79 // function to register itself as the native platform.
80 GetDefaultPlatformSP () = platform_sp;
81}
82
Greg Claytone996fd32011-03-08 22:40:15 +000083Error
Greg Claytond314e812011-03-23 00:09:55 +000084Platform::GetFile (const FileSpec &platform_file,
85 const UUID *uuid_ptr,
86 FileSpec &local_file)
Greg Claytone996fd32011-03-08 22:40:15 +000087{
88 // Default to the local case
89 local_file = platform_file;
90 return Error();
91}
92
Greg Clayton91c0e742013-01-11 23:44:27 +000093FileSpecList
94Platform::LocateExecutableScriptingResources (Target *target, Module &module)
Enrico Granata17598482012-11-08 02:22:02 +000095{
Greg Clayton91c0e742013-01-11 23:44:27 +000096 return FileSpecList();
Enrico Granata17598482012-11-08 02:22:02 +000097}
98
Jason Molenda1c627542013-04-05 01:03:25 +000099Platform*
Greg Clayton57abc5d2013-05-10 21:47:16 +0000100Platform::FindPlugin (Process *process, const ConstString &plugin_name)
Jason Molenda1c627542013-04-05 01:03:25 +0000101{
102 PlatformCreateInstance create_callback = NULL;
103 if (plugin_name)
104 {
105 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
106 if (create_callback)
107 {
108 ArchSpec arch;
109 if (process)
110 {
111 arch = process->GetTarget().GetArchitecture();
112 }
Greg Clayton7b0992d2013-04-18 22:45:39 +0000113 std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
Jason Molenda1c627542013-04-05 01:03:25 +0000114 if (instance_ap.get())
115 return instance_ap.release();
116 }
117 }
118 else
119 {
120 for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
121 {
Matt Kopecef143712013-06-03 18:00:07 +0000122 std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
Jason Molenda1c627542013-04-05 01:03:25 +0000123 if (instance_ap.get())
124 return instance_ap.release();
125 }
126 }
127 return NULL;
128}
129
Greg Clayton32e0a752011-03-30 18:16:51 +0000130Error
Greg Claytonb9a01b32012-02-26 05:51:37 +0000131Platform::GetSharedModule (const ModuleSpec &module_spec,
Greg Clayton32e0a752011-03-30 18:16:51 +0000132 ModuleSP &module_sp,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000133 const FileSpecList *module_search_paths_ptr,
Greg Clayton32e0a752011-03-30 18:16:51 +0000134 ModuleSP *old_module_sp_ptr,
135 bool *did_create_ptr)
136{
137 // Don't do any path remapping for the default implementation
138 // of the platform GetSharedModule function, just call through
139 // to our static ModuleList function. Platform subclasses that
140 // implement remote debugging, might have a developer kits
141 // installed that have cached versions of the files for the
142 // remote target, or might implement a download and cache
143 // locally implementation.
144 const bool always_create = false;
Greg Claytonb9a01b32012-02-26 05:51:37 +0000145 return ModuleList::GetSharedModule (module_spec,
Greg Clayton32e0a752011-03-30 18:16:51 +0000146 module_sp,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000147 module_search_paths_ptr,
Greg Clayton32e0a752011-03-30 18:16:51 +0000148 old_module_sp_ptr,
149 did_create_ptr,
150 always_create);
151}
152
Greg Claytone996fd32011-03-08 22:40:15 +0000153PlatformSP
Greg Claytonded470d2011-03-19 01:12:21 +0000154Platform::Create (const char *platform_name, Error &error)
Greg Claytone996fd32011-03-08 22:40:15 +0000155{
156 PlatformCreateInstance create_callback = NULL;
157 lldb::PlatformSP platform_sp;
Greg Claytonded470d2011-03-19 01:12:21 +0000158 if (platform_name && platform_name[0])
Greg Claytone996fd32011-03-08 22:40:15 +0000159 {
Greg Clayton57abc5d2013-05-10 21:47:16 +0000160 ConstString const_platform_name (platform_name);
161 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
Greg Claytone996fd32011-03-08 22:40:15 +0000162 if (create_callback)
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000163 platform_sp.reset(create_callback(true, NULL));
Greg Claytone996fd32011-03-08 22:40:15 +0000164 else
Greg Claytonded470d2011-03-19 01:12:21 +0000165 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
Greg Claytone996fd32011-03-08 22:40:15 +0000166 }
167 else
Greg Claytonded470d2011-03-19 01:12:21 +0000168 error.SetErrorString ("invalid platform name");
Greg Claytone996fd32011-03-08 22:40:15 +0000169 return platform_sp;
170}
171
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000172
173PlatformSP
Greg Clayton70512312012-05-08 01:45:38 +0000174Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000175{
176 lldb::PlatformSP platform_sp;
177 if (arch.IsValid())
178 {
Greg Clayton70512312012-05-08 01:45:38 +0000179 uint32_t idx;
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000180 PlatformCreateInstance create_callback;
Greg Clayton1e0c8842013-01-11 20:49:54 +0000181 // First try exact arch matches across all platform plug-ins
182 bool exact = true;
Greg Clayton70512312012-05-08 01:45:38 +0000183 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000184 {
185 if (create_callback)
Greg Clayton1e0c8842013-01-11 20:49:54 +0000186 {
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000187 platform_sp.reset(create_callback(false, &arch));
Greg Clayton1e0c8842013-01-11 20:49:54 +0000188 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
189 return platform_sp;
190 }
191 }
192 // Next try compatible arch matches across all platform plug-ins
193 exact = false;
194 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
195 {
196 if (create_callback)
197 {
198 platform_sp.reset(create_callback(false, &arch));
199 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
200 return platform_sp;
201 }
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000202 }
203 }
204 else
205 error.SetErrorString ("invalid platform name");
Greg Clayton70512312012-05-08 01:45:38 +0000206 if (platform_arch_ptr)
207 platform_arch_ptr->Clear();
208 platform_sp.reset();
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000209 return platform_sp;
210}
211
Greg Claytone996fd32011-03-08 22:40:15 +0000212uint32_t
213Platform::GetNumConnectedRemotePlatforms ()
214{
215 Mutex::Locker locker (GetConnectedPlatformListMutex ());
216 return GetConnectedPlatformList().size();
217}
218
219PlatformSP
220Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
221{
222 PlatformSP platform_sp;
223 {
224 Mutex::Locker locker (GetConnectedPlatformListMutex ());
225 if (idx < GetConnectedPlatformList().size())
226 platform_sp = GetConnectedPlatformList ()[idx];
227 }
228 return platform_sp;
229}
230
231//------------------------------------------------------------------
232/// Default Constructor
233//------------------------------------------------------------------
Greg Claytonded470d2011-03-19 01:12:21 +0000234Platform::Platform (bool is_host) :
235 m_is_host (is_host),
Greg Claytonded470d2011-03-19 01:12:21 +0000236 m_os_version_set_while_connected (false),
237 m_system_arch_set_while_connected (false),
Greg Claytonf3dd93c2011-06-17 03:31:01 +0000238 m_sdk_sysroot (),
239 m_sdk_build (),
Greg Claytonded470d2011-03-19 01:12:21 +0000240 m_remote_url (),
Greg Clayton1cb64962011-03-24 04:28:38 +0000241 m_name (),
Greg Claytonded470d2011-03-19 01:12:21 +0000242 m_major_os_version (UINT32_MAX),
243 m_minor_os_version (UINT32_MAX),
Greg Clayton32e0a752011-03-30 18:16:51 +0000244 m_update_os_version (UINT32_MAX),
245 m_system_arch(),
246 m_uid_map_mutex (Mutex::eMutexTypeNormal),
247 m_gid_map_mutex (Mutex::eMutexTypeNormal),
248 m_uid_map(),
249 m_gid_map(),
250 m_max_uid_name_len (0),
Daniel Maleae0f8f572013-08-26 23:57:52 +0000251 m_max_gid_name_len (0),
252 m_supports_rsync (false),
253 m_rsync_opts (),
254 m_rsync_prefix (),
255 m_supports_ssh (false),
256 m_ssh_opts (),
257 m_ignores_remote_hostname (false)
Greg Claytone996fd32011-03-08 22:40:15 +0000258{
Greg Clayton5160ce52013-03-27 23:08:40 +0000259 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Greg Clayton8b82f082011-04-12 05:54:46 +0000260 if (log)
261 log->Printf ("%p Platform::Platform()", this);
Greg Claytone996fd32011-03-08 22:40:15 +0000262}
263
264//------------------------------------------------------------------
265/// Destructor.
266///
267/// The destructor is virtual since this class is designed to be
268/// inherited from by the plug-in instance.
269//------------------------------------------------------------------
270Platform::~Platform()
271{
Greg Clayton5160ce52013-03-27 23:08:40 +0000272 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Greg Clayton8b82f082011-04-12 05:54:46 +0000273 if (log)
274 log->Printf ("%p Platform::~Platform()", this);
Greg Claytone996fd32011-03-08 22:40:15 +0000275}
276
Greg Clayton1cb64962011-03-24 04:28:38 +0000277void
278Platform::GetStatus (Stream &strm)
279{
280 uint32_t major = UINT32_MAX;
281 uint32_t minor = UINT32_MAX;
282 uint32_t update = UINT32_MAX;
283 std::string s;
Greg Clayton57abc5d2013-05-10 21:47:16 +0000284 strm.Printf (" Platform: %s\n", GetPluginName().GetCString());
Greg Clayton1cb64962011-03-24 04:28:38 +0000285
286 ArchSpec arch (GetSystemArchitecture());
287 if (arch.IsValid())
288 {
289 if (!arch.GetTriple().str().empty())
Greg Clayton32e0a752011-03-30 18:16:51 +0000290 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
Greg Clayton1cb64962011-03-24 04:28:38 +0000291 }
292
293 if (GetOSVersion(major, minor, update))
294 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000295 strm.Printf("OS Version: %u", major);
Greg Clayton1cb64962011-03-24 04:28:38 +0000296 if (minor != UINT32_MAX)
297 strm.Printf(".%u", minor);
298 if (update != UINT32_MAX)
299 strm.Printf(".%u", update);
300
301 if (GetOSBuildString (s))
302 strm.Printf(" (%s)", s.c_str());
303
304 strm.EOL();
305 }
306
307 if (GetOSKernelDescription (s))
Greg Clayton32e0a752011-03-30 18:16:51 +0000308 strm.Printf(" Kernel: %s\n", s.c_str());
Greg Clayton1cb64962011-03-24 04:28:38 +0000309
310 if (IsHost())
311 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000312 strm.Printf(" Hostname: %s\n", GetHostname());
Greg Clayton1cb64962011-03-24 04:28:38 +0000313 }
314 else
315 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000316 const bool is_connected = IsConnected();
317 if (is_connected)
318 strm.Printf(" Hostname: %s\n", GetHostname());
319 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
Greg Clayton1cb64962011-03-24 04:28:38 +0000320 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000321
322 if (!IsConnected())
323 return;
324
325 std::string specific_info(GetPlatformSpecificConnectionInformation());
326
327 if (specific_info.empty() == false)
328 strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
Greg Clayton1cb64962011-03-24 04:28:38 +0000329}
330
Greg Claytonded470d2011-03-19 01:12:21 +0000331
332bool
333Platform::GetOSVersion (uint32_t &major,
334 uint32_t &minor,
335 uint32_t &update)
336{
337 bool success = m_major_os_version != UINT32_MAX;
338 if (IsHost())
339 {
340 if (!success)
341 {
342 // We have a local host platform
343 success = Host::GetOSVersion (m_major_os_version,
344 m_minor_os_version,
345 m_update_os_version);
346 m_os_version_set_while_connected = success;
347 }
348 }
349 else
350 {
351 // We have a remote platform. We can only fetch the remote
352 // OS version if we are connected, and we don't want to do it
353 // more than once.
354
355 const bool is_connected = IsConnected();
356
Greg Clayton1cb64962011-03-24 04:28:38 +0000357 bool fetch = false;
Greg Claytonded470d2011-03-19 01:12:21 +0000358 if (success)
359 {
360 // We have valid OS version info, check to make sure it wasn't
361 // manually set prior to connecting. If it was manually set prior
362 // to connecting, then lets fetch the actual OS version info
363 // if we are now connected.
364 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton1cb64962011-03-24 04:28:38 +0000365 fetch = true;
Greg Claytonded470d2011-03-19 01:12:21 +0000366 }
367 else
368 {
369 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton1cb64962011-03-24 04:28:38 +0000370 fetch = is_connected;
Greg Claytonded470d2011-03-19 01:12:21 +0000371 }
372
Greg Clayton1cb64962011-03-24 04:28:38 +0000373 if (fetch)
Greg Claytonded470d2011-03-19 01:12:21 +0000374 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000375 success = GetRemoteOSVersion ();
Greg Claytonded470d2011-03-19 01:12:21 +0000376 m_os_version_set_while_connected = success;
377 }
378 }
379
380 if (success)
381 {
382 major = m_major_os_version;
383 minor = m_minor_os_version;
384 update = m_update_os_version;
385 }
386 return success;
387}
Greg Clayton1cb64962011-03-24 04:28:38 +0000388
389bool
390Platform::GetOSBuildString (std::string &s)
391{
392 if (IsHost())
393 return Host::GetOSBuildString (s);
394 else
395 return GetRemoteOSBuildString (s);
396}
397
398bool
399Platform::GetOSKernelDescription (std::string &s)
400{
401 if (IsHost())
402 return Host::GetOSKernelDescription (s);
403 else
404 return GetRemoteOSKernelDescription (s);
405}
406
Greg Clayton57abc5d2013-05-10 21:47:16 +0000407ConstString
Greg Clayton8b82f082011-04-12 05:54:46 +0000408Platform::GetName ()
409{
410 const char *name = GetHostname();
411 if (name == NULL || name[0] == '\0')
Greg Clayton57abc5d2013-05-10 21:47:16 +0000412 return GetPluginName();
413 return ConstString (name);
Greg Clayton8b82f082011-04-12 05:54:46 +0000414}
415
416const char *
Greg Clayton1cb64962011-03-24 04:28:38 +0000417Platform::GetHostname ()
418{
Greg Claytonab65b342011-04-13 22:47:15 +0000419 if (IsHost())
420 return "localhost";
Greg Clayton32e0a752011-03-30 18:16:51 +0000421
422 if (m_name.empty())
423 return NULL;
424 return m_name.c_str();
425}
426
427const char *
428Platform::GetUserName (uint32_t uid)
429{
430 const char *user_name = GetCachedUserName(uid);
431 if (user_name)
432 return user_name;
433 if (IsHost())
434 {
435 std::string name;
436 if (Host::GetUserName(uid, name))
437 return SetCachedUserName (uid, name.c_str(), name.size());
438 }
Greg Clayton1cb64962011-03-24 04:28:38 +0000439 return NULL;
440}
441
Greg Clayton32e0a752011-03-30 18:16:51 +0000442const char *
443Platform::GetGroupName (uint32_t gid)
444{
445 const char *group_name = GetCachedGroupName(gid);
446 if (group_name)
447 return group_name;
448 if (IsHost())
449 {
450 std::string name;
451 if (Host::GetGroupName(gid, name))
452 return SetCachedGroupName (gid, name.c_str(), name.size());
453 }
454 return NULL;
455}
Greg Clayton1cb64962011-03-24 04:28:38 +0000456
Greg Claytonded470d2011-03-19 01:12:21 +0000457bool
458Platform::SetOSVersion (uint32_t major,
459 uint32_t minor,
460 uint32_t update)
461{
462 if (IsHost())
463 {
464 // We don't need anyone setting the OS version for the host platform,
465 // we should be able to figure it out by calling Host::GetOSVersion(...).
466 return false;
467 }
468 else
469 {
470 // We have a remote platform, allow setting the target OS version if
471 // we aren't connected, since if we are connected, we should be able to
472 // request the remote OS version from the connected platform.
473 if (IsConnected())
474 return false;
475 else
476 {
477 // We aren't connected and we might want to set the OS version
478 // ahead of time before we connect so we can peruse files and
479 // use a local SDK or PDK cache of support files to disassemble
480 // or do other things.
481 m_major_os_version = major;
482 m_minor_os_version = minor;
483 m_update_os_version = update;
484 return true;
485 }
486 }
487 return false;
488}
489
490
Greg Claytone996fd32011-03-08 22:40:15 +0000491Error
492Platform::ResolveExecutable (const FileSpec &exe_file,
493 const ArchSpec &exe_arch,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000494 lldb::ModuleSP &exe_module_sp,
495 const FileSpecList *module_search_paths_ptr)
Greg Claytone996fd32011-03-08 22:40:15 +0000496{
497 Error error;
498 if (exe_file.Exists())
499 {
Greg Claytonb9a01b32012-02-26 05:51:37 +0000500 ModuleSpec module_spec (exe_file, exe_arch);
501 if (module_spec.GetArchitecture().IsValid())
Greg Claytone996fd32011-03-08 22:40:15 +0000502 {
Greg Claytonb9a01b32012-02-26 05:51:37 +0000503 error = ModuleList::GetSharedModule (module_spec,
Greg Claytone996fd32011-03-08 22:40:15 +0000504 exe_module_sp,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000505 module_search_paths_ptr,
Greg Claytone996fd32011-03-08 22:40:15 +0000506 NULL,
507 NULL);
508 }
509 else
510 {
511 // No valid architecture was specified, ask the platform for
512 // the architectures that we should be using (in the correct order)
513 // and see if we can find a match that way
Greg Claytonb9a01b32012-02-26 05:51:37 +0000514 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
Greg Claytone996fd32011-03-08 22:40:15 +0000515 {
Greg Claytonb9a01b32012-02-26 05:51:37 +0000516 error = ModuleList::GetSharedModule (module_spec,
Greg Claytone996fd32011-03-08 22:40:15 +0000517 exe_module_sp,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000518 module_search_paths_ptr,
Greg Claytone996fd32011-03-08 22:40:15 +0000519 NULL,
520 NULL);
521 // Did we find an executable using one of the
522 if (error.Success() && exe_module_sp)
523 break;
524 }
525 }
526 }
527 else
528 {
Greg Claytonb5ad4ec2013-04-29 17:25:54 +0000529 error.SetErrorStringWithFormat ("'%s' does not exist",
530 exe_file.GetPath().c_str());
Greg Claytone996fd32011-03-08 22:40:15 +0000531 }
532 return error;
533}
534
Greg Clayton103f0282012-09-12 02:03:59 +0000535Error
536Platform::ResolveSymbolFile (Target &target,
537 const ModuleSpec &sym_spec,
538 FileSpec &sym_file)
539{
540 Error error;
541 if (sym_spec.GetSymbolFileSpec().Exists())
542 sym_file = sym_spec.GetSymbolFileSpec();
543 else
544 error.SetErrorString("unable to resolve symbol file");
545 return error;
546
547}
548
549
550
Greg Claytonaa516842011-08-11 16:25:18 +0000551bool
552Platform::ResolveRemotePath (const FileSpec &platform_path,
553 FileSpec &resolved_platform_path)
554{
555 resolved_platform_path = platform_path;
556 return resolved_platform_path.ResolvePath();
557}
558
Greg Claytonded470d2011-03-19 01:12:21 +0000559
560const ArchSpec &
561Platform::GetSystemArchitecture()
562{
563 if (IsHost())
564 {
565 if (!m_system_arch.IsValid())
566 {
567 // We have a local host platform
568 m_system_arch = Host::GetArchitecture();
569 m_system_arch_set_while_connected = m_system_arch.IsValid();
570 }
571 }
572 else
573 {
574 // We have a remote platform. We can only fetch the remote
575 // system architecture if we are connected, and we don't want to do it
576 // more than once.
577
578 const bool is_connected = IsConnected();
579
580 bool fetch = false;
581 if (m_system_arch.IsValid())
582 {
583 // We have valid OS version info, check to make sure it wasn't
584 // manually set prior to connecting. If it was manually set prior
585 // to connecting, then lets fetch the actual OS version info
586 // if we are now connected.
587 if (is_connected && !m_system_arch_set_while_connected)
588 fetch = true;
589 }
590 else
591 {
592 // We don't have valid OS version info, fetch it if we are connected
593 fetch = is_connected;
594 }
595
596 if (fetch)
597 {
Greg Clayton1cb64962011-03-24 04:28:38 +0000598 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonded470d2011-03-19 01:12:21 +0000599 m_system_arch_set_while_connected = m_system_arch.IsValid();
600 }
601 }
602 return m_system_arch;
603}
604
605
Greg Claytone996fd32011-03-08 22:40:15 +0000606Error
Greg Claytond314e812011-03-23 00:09:55 +0000607Platform::ConnectRemote (Args& args)
Greg Claytone996fd32011-03-08 22:40:15 +0000608{
609 Error error;
Greg Claytond314e812011-03-23 00:09:55 +0000610 if (IsHost())
Greg Clayton57abc5d2013-05-10 21:47:16 +0000611 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
Greg Claytond314e812011-03-23 00:09:55 +0000612 else
Greg Clayton57abc5d2013-05-10 21:47:16 +0000613 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
Greg Claytone996fd32011-03-08 22:40:15 +0000614 return error;
615}
616
617Error
Greg Claytond314e812011-03-23 00:09:55 +0000618Platform::DisconnectRemote ()
Greg Claytone996fd32011-03-08 22:40:15 +0000619{
620 Error error;
Greg Claytond314e812011-03-23 00:09:55 +0000621 if (IsHost())
Greg Clayton57abc5d2013-05-10 21:47:16 +0000622 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
Greg Claytond314e812011-03-23 00:09:55 +0000623 else
Greg Clayton57abc5d2013-05-10 21:47:16 +0000624 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
Greg Claytone996fd32011-03-08 22:40:15 +0000625 return error;
626}
Greg Clayton32e0a752011-03-30 18:16:51 +0000627
628bool
Greg Clayton8b82f082011-04-12 05:54:46 +0000629Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
Greg Clayton32e0a752011-03-30 18:16:51 +0000630{
631 // Take care of the host case so that each subclass can just
Greg Clayton8b82f082011-04-12 05:54:46 +0000632 // call this function to get the host functionality.
Greg Clayton32e0a752011-03-30 18:16:51 +0000633 if (IsHost())
634 return Host::GetProcessInfo (pid, process_info);
635 return false;
636}
637
638uint32_t
Greg Clayton8b82f082011-04-12 05:54:46 +0000639Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
640 ProcessInstanceInfoList &process_infos)
Greg Clayton32e0a752011-03-30 18:16:51 +0000641{
Greg Clayton8b82f082011-04-12 05:54:46 +0000642 // Take care of the host case so that each subclass can just
643 // call this function to get the host functionality.
Greg Clayton32e0a752011-03-30 18:16:51 +0000644 uint32_t match_count = 0;
645 if (IsHost())
646 match_count = Host::FindProcesses (match_info, process_infos);
647 return match_count;
648}
Greg Clayton8b82f082011-04-12 05:54:46 +0000649
650
651Error
652Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
653{
654 Error error;
655 // Take care of the host case so that each subclass can just
656 // call this function to get the host functionality.
657 if (IsHost())
Greg Clayton84db9102012-03-26 23:03:23 +0000658 {
659 if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
660 launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
661
662 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
663 {
664 const bool is_localhost = true;
Greg Claytond1cf11a2012-04-14 01:42:46 +0000665 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
666 const bool first_arg_is_full_shell_command = false;
Jim Inghamd3990792013-09-11 18:23:22 +0000667 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
Greg Claytond1cf11a2012-04-14 01:42:46 +0000668 if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
669 is_localhost,
670 will_debug,
Jim Inghamdf0ae222013-09-10 02:09:47 +0000671 first_arg_is_full_shell_command,
672 num_resumes))
Greg Clayton84db9102012-03-26 23:03:23 +0000673 return error;
674 }
675
Greg Clayton8b82f082011-04-12 05:54:46 +0000676 error = Host::LaunchProcess (launch_info);
Greg Clayton84db9102012-03-26 23:03:23 +0000677 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000678 else
679 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
680 return error;
681}
682
683lldb::ProcessSP
684Platform::DebugProcess (ProcessLaunchInfo &launch_info,
685 Debugger &debugger,
686 Target *target, // Can be NULL, if NULL create a new target, else use existing one
687 Listener &listener,
688 Error &error)
689{
690 ProcessSP process_sp;
691 // Make sure we stop at the entry point
692 launch_info.GetFlags ().Set (eLaunchFlagDebug);
Jim Inghamb4451b12012-06-01 01:22:13 +0000693 // We always launch the process we are going to debug in a separate process
694 // group, since then we can handle ^C interrupts ourselves w/o having to worry
695 // about the target getting them as well.
696 launch_info.SetLaunchInSeparateProcessGroup(true);
697
Greg Clayton8b82f082011-04-12 05:54:46 +0000698 error = LaunchProcess (launch_info);
699 if (error.Success())
700 {
Greg Clayton144f3a92011-11-15 03:53:30 +0000701 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
Greg Clayton8b82f082011-04-12 05:54:46 +0000702 {
Greg Clayton144f3a92011-11-15 03:53:30 +0000703 ProcessAttachInfo attach_info (launch_info);
704 process_sp = Attach (attach_info, debugger, target, listener, error);
Greg Claytone24c4ac2011-11-17 04:46:02 +0000705 if (process_sp)
706 {
707 // Since we attached to the process, it will think it needs to detach
708 // if the process object just goes away without an explicit call to
709 // Process::Kill() or Process::Detach(), so let it know to kill the
710 // process if this happens.
711 process_sp->SetShouldDetach (false);
Greg Claytonee95ed52011-11-17 22:14:31 +0000712
713 // If we didn't have any file actions, the pseudo terminal might
714 // have been used where the slave side was given as the file to
715 // open for stdin/out/err after we have already opened the master
716 // so we can read/write stdin/out/err.
717 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
718 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
719 {
720 process_sp->SetSTDIOFileDescriptor(pty_fd);
721 }
Greg Claytone24c4ac2011-11-17 04:46:02 +0000722 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000723 }
724 }
725 return process_sp;
726}
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000727
728
729lldb::PlatformSP
Greg Clayton70512312012-05-08 01:45:38 +0000730Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000731{
732 lldb::PlatformSP platform_sp;
733 Error error;
734 if (arch.IsValid())
Greg Clayton70512312012-05-08 01:45:38 +0000735 platform_sp = Platform::Create (arch, platform_arch_ptr, error);
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000736 return platform_sp;
737}
738
739
740//------------------------------------------------------------------
741/// Lets a platform answer if it is compatible with a given
742/// architecture and the target triple contained within.
743//------------------------------------------------------------------
744bool
Greg Clayton1e0c8842013-01-11 20:49:54 +0000745Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000746{
747 // If the architecture is invalid, we must answer true...
Greg Clayton70512312012-05-08 01:45:38 +0000748 if (arch.IsValid())
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000749 {
Greg Clayton70512312012-05-08 01:45:38 +0000750 ArchSpec platform_arch;
Greg Clayton1e0c8842013-01-11 20:49:54 +0000751 // Try for an exact architecture match first.
752 if (exact_arch_match)
Greg Clayton70512312012-05-08 01:45:38 +0000753 {
Greg Clayton1e0c8842013-01-11 20:49:54 +0000754 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
Greg Clayton70512312012-05-08 01:45:38 +0000755 {
Greg Clayton1e0c8842013-01-11 20:49:54 +0000756 if (arch.IsExactMatch(platform_arch))
757 {
758 if (compatible_arch_ptr)
759 *compatible_arch_ptr = platform_arch;
760 return true;
761 }
762 }
763 }
764 else
765 {
766 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
767 {
768 if (arch.IsCompatibleMatch(platform_arch))
769 {
770 if (compatible_arch_ptr)
771 *compatible_arch_ptr = platform_arch;
772 return true;
773 }
Greg Clayton70512312012-05-08 01:45:38 +0000774 }
775 }
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000776 }
Greg Clayton70512312012-05-08 01:45:38 +0000777 if (compatible_arch_ptr)
778 compatible_arch_ptr->Clear();
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000779 return false;
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000780}
781
Daniel Maleae0f8f572013-08-26 23:57:52 +0000782uint32_t
783Platform::MakeDirectory (const FileSpec &spec,
784 mode_t mode)
785{
786 std::string path(spec.GetPath());
787 return this->MakeDirectory(path,mode);
788}
789
790Error
791Platform::PutFile (const FileSpec& source,
792 const FileSpec& destination,
793 uint32_t uid,
794 uint32_t gid)
795{
796 Error error("unimplemented");
797 return error;
798}
799
800Error
801Platform::GetFile (const FileSpec& source,
802 const FileSpec& destination)
803{
804 Error error("unimplemented");
805 return error;
806}
807
808bool
809Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
810{
811 return false;
812}
813
814lldb_private::Error
815Platform::RunShellCommand (const char *command, // Shouldn't be NULL
816 const char *working_dir, // Pass NULL to use the current working directory
817 int *status_ptr, // Pass NULL if you don't want the process exit status
818 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
819 std::string *command_output, // Pass NULL if you don't want the command output
820 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
821{
822 if (IsHost())
823 return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
824 else
825 return Error("unimplemented");
826}
827
828
829bool
830Platform::CalculateMD5 (const FileSpec& file_spec,
831 uint64_t &low,
832 uint64_t &high)
833{
834 if (IsHost())
835 return Host::CalculateMD5(file_spec, low, high);
836 else
837 return false;
838}
839
840void
841Platform::SetLocalCacheDirectory (const char* local)
842{
843 m_local_cache_directory.assign(local);
844}
845
846const char*
847Platform::GetLocalCacheDirectory ()
848{
849 return m_local_cache_directory.c_str();
850}
851
852static OptionDefinition
853g_rsync_option_table[] =
854{
Virgile Belloe2607b52013-09-05 16:42:23 +0000855 { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable rsync." },
856 { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." },
857 { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." },
858 { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." },
Daniel Maleae0f8f572013-08-26 23:57:52 +0000859};
860
861static OptionDefinition
862g_ssh_option_table[] =
863{
Virgile Belloe2607b52013-09-05 16:42:23 +0000864 { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable SSH." },
865 { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." },
Daniel Maleae0f8f572013-08-26 23:57:52 +0000866};
867
868static OptionDefinition
869g_caching_option_table[] =
870{
Virgile Belloe2607b52013-09-05 16:42:23 +0000871 { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath , "Path in which to store local copies of files." },
Daniel Maleae0f8f572013-08-26 23:57:52 +0000872};
873
874OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
875{
876}
877
878OptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
879{
880}
881
882const lldb_private::OptionDefinition*
883OptionGroupPlatformRSync::GetDefinitions ()
884{
885 return g_rsync_option_table;
886}
887
888void
889OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
890{
891 m_rsync = false;
892 m_rsync_opts.clear();
893 m_rsync_prefix.clear();
894 m_ignores_remote_hostname = false;
895}
896
897lldb_private::Error
898OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
899 uint32_t option_idx,
900 const char *option_arg)
901{
902 Error error;
903 char short_option = (char) GetDefinitions()[option_idx].short_option;
904 switch (short_option)
905 {
906 case 'r':
907 m_rsync = true;
908 break;
909
910 case 'R':
911 m_rsync_opts.assign(option_arg);
912 break;
913
914 case 'P':
915 m_rsync_prefix.assign(option_arg);
916 break;
917
918 case 'i':
919 m_ignores_remote_hostname = true;
920 break;
921
922 default:
923 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
924 break;
925 }
926
927 return error;
928}
929
930uint32_t
931OptionGroupPlatformRSync::GetNumDefinitions ()
932{
933 return llvm::array_lengthof(g_rsync_option_table);
934}
Greg Clayton1e0c8842013-01-11 20:49:54 +0000935
Greg Clayton4116e932012-05-15 02:33:01 +0000936lldb::BreakpointSP
937Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
938{
939 return lldb::BreakpointSP();
940}
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000941
Daniel Maleae0f8f572013-08-26 23:57:52 +0000942OptionGroupPlatformSSH::OptionGroupPlatformSSH ()
943{
944}
945
946OptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
947{
948}
949
950const lldb_private::OptionDefinition*
951OptionGroupPlatformSSH::GetDefinitions ()
952{
953 return g_ssh_option_table;
954}
955
956void
957OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
958{
959 m_ssh = false;
960 m_ssh_opts.clear();
961}
962
963lldb_private::Error
964OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
965 uint32_t option_idx,
966 const char *option_arg)
967{
968 Error error;
969 char short_option = (char) GetDefinitions()[option_idx].short_option;
970 switch (short_option)
971 {
972 case 's':
973 m_ssh = true;
974 break;
975
976 case 'S':
977 m_ssh_opts.assign(option_arg);
978 break;
979
980 default:
981 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
982 break;
983 }
984
985 return error;
986}
987
988uint32_t
989OptionGroupPlatformSSH::GetNumDefinitions ()
990{
991 return llvm::array_lengthof(g_ssh_option_table);
992}
993
994OptionGroupPlatformCaching::OptionGroupPlatformCaching ()
995{
996}
997
998OptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
999{
1000}
1001
1002const lldb_private::OptionDefinition*
1003OptionGroupPlatformCaching::GetDefinitions ()
1004{
1005 return g_caching_option_table;
1006}
1007
1008void
1009OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
1010{
1011 m_cache_dir.clear();
1012}
1013
1014lldb_private::Error
1015OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
1016 uint32_t option_idx,
1017 const char *option_arg)
1018{
1019 Error error;
1020 char short_option = (char) GetDefinitions()[option_idx].short_option;
1021 switch (short_option)
1022 {
1023 case 'c':
1024 m_cache_dir.assign(option_arg);
1025 break;
1026
1027 default:
1028 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1029 break;
1030 }
1031
1032 return error;
1033}
1034
1035uint32_t
1036OptionGroupPlatformCaching::GetNumDefinitions ()
1037{
1038 return llvm::array_lengthof(g_caching_option_table);
1039}
1040
Greg Clayton67cc0632012-08-22 17:17:09 +00001041size_t
1042Platform::GetEnvironment (StringList &environment)
1043{
1044 environment.Clear();
1045 return false;
1046}