1 //===-- 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/Breakpoint/BreakpointIDList.h"
17 #include "lldb/Core/Error.h"
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/ModuleSpec.h"
20 #include "lldb/Core/PluginManager.h"
21 #include "lldb/Host/FileSpec.h"
22 #include "lldb/Host/FileSystem.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Utility/Utils.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 // Use a singleton function for g_local_platform_sp to avoid init
33 // constructors since LLDB is often part of a shared library
34 static PlatformSP&
35 GetDefaultPlatformSP ()
36 {
37     static PlatformSP g_default_platform_sp;
38     return g_default_platform_sp;
39 }
40 
41 static Mutex &
42 GetConnectedPlatformListMutex ()
43 {
44     static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
45     return g_remote_connected_platforms_mutex;
46 }
47 static std::vector<PlatformSP> &
48 GetConnectedPlatformList ()
49 {
50     static std::vector<PlatformSP> g_remote_connected_platforms;
51     return g_remote_connected_platforms;
52 }
53 
54 
55 const char *
56 Platform::GetHostPlatformName ()
57 {
58     return "host";
59 }
60 
61 //------------------------------------------------------------------
62 /// Get the native host platform plug-in.
63 ///
64 /// There should only be one of these for each host that LLDB runs
65 /// upon that should be statically compiled in and registered using
66 /// preprocessor macros or other similar build mechanisms.
67 ///
68 /// This platform will be used as the default platform when launching
69 /// or attaching to processes unless another platform is specified.
70 //------------------------------------------------------------------
71 PlatformSP
72 Platform::GetDefaultPlatform ()
73 {
74     return GetDefaultPlatformSP ();
75 }
76 
77 void
78 Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
79 {
80     // The native platform should use its static void Platform::Initialize()
81     // function to register itself as the native platform.
82     GetDefaultPlatformSP () = platform_sp;
83 }
84 
85 Error
86 Platform::GetFileWithUUID (const FileSpec &platform_file,
87                            const UUID *uuid_ptr,
88                            FileSpec &local_file)
89 {
90     // Default to the local case
91     local_file = platform_file;
92     return Error();
93 }
94 
95 FileSpecList
96 Platform::LocateExecutableScriptingResources (Target *target, Module &module, Stream* feedback_stream)
97 {
98     return FileSpecList();
99 }
100 
101 Platform*
102 Platform::FindPlugin (Process *process, const ConstString &plugin_name)
103 {
104     PlatformCreateInstance create_callback = NULL;
105     if (plugin_name)
106     {
107         create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
108         if (create_callback)
109         {
110             ArchSpec arch;
111             if (process)
112             {
113                 arch = process->GetTarget().GetArchitecture();
114             }
115             std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
116             if (instance_ap.get())
117                 return instance_ap.release();
118         }
119     }
120     else
121     {
122         for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
123         {
124             std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
125             if (instance_ap.get())
126                 return instance_ap.release();
127         }
128     }
129     return NULL;
130 }
131 
132 Error
133 Platform::GetSharedModule (const ModuleSpec &module_spec,
134                            ModuleSP &module_sp,
135                            const FileSpecList *module_search_paths_ptr,
136                            ModuleSP *old_module_sp_ptr,
137                            bool *did_create_ptr)
138 {
139     // Don't do any path remapping for the default implementation
140     // of the platform GetSharedModule function, just call through
141     // to our static ModuleList function. Platform subclasses that
142     // implement remote debugging, might have a developer kits
143     // installed that have cached versions of the files for the
144     // remote target, or might implement a download and cache
145     // locally implementation.
146     const bool always_create = false;
147     return ModuleList::GetSharedModule (module_spec,
148                                         module_sp,
149                                         module_search_paths_ptr,
150                                         old_module_sp_ptr,
151                                         did_create_ptr,
152                                         always_create);
153 }
154 
155 PlatformSP
156 Platform::Create (const char *platform_name, Error &error)
157 {
158     PlatformCreateInstance create_callback = NULL;
159     lldb::PlatformSP platform_sp;
160     if (platform_name && platform_name[0])
161     {
162         ConstString const_platform_name (platform_name);
163         create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
164         if (create_callback)
165             platform_sp.reset(create_callback(true, NULL));
166         else
167             error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
168     }
169     else
170         error.SetErrorString ("invalid platform name");
171     return platform_sp;
172 }
173 
174 
175 PlatformSP
176 Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
177 {
178     lldb::PlatformSP platform_sp;
179     if (arch.IsValid())
180     {
181         uint32_t idx;
182         PlatformCreateInstance create_callback;
183         // First try exact arch matches across all platform plug-ins
184         bool exact = true;
185         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
186         {
187             if (create_callback)
188             {
189                 platform_sp.reset(create_callback(false, &arch));
190                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
191                     return platform_sp;
192             }
193         }
194         // Next try compatible arch matches across all platform plug-ins
195         exact = false;
196         for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
197         {
198             if (create_callback)
199             {
200                 platform_sp.reset(create_callback(false, &arch));
201                 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
202                     return platform_sp;
203             }
204         }
205     }
206     else
207         error.SetErrorString ("invalid platform name");
208     if (platform_arch_ptr)
209         platform_arch_ptr->Clear();
210     platform_sp.reset();
211     return platform_sp;
212 }
213 
214 uint32_t
215 Platform::GetNumConnectedRemotePlatforms ()
216 {
217     Mutex::Locker locker (GetConnectedPlatformListMutex ());
218     return GetConnectedPlatformList().size();
219 }
220 
221 PlatformSP
222 Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
223 {
224     PlatformSP platform_sp;
225     {
226         Mutex::Locker locker (GetConnectedPlatformListMutex ());
227         if (idx < GetConnectedPlatformList().size())
228             platform_sp = GetConnectedPlatformList ()[idx];
229     }
230     return platform_sp;
231 }
232 
233 //------------------------------------------------------------------
234 /// Default Constructor
235 //------------------------------------------------------------------
236 Platform::Platform (bool is_host) :
237     m_is_host (is_host),
238     m_os_version_set_while_connected (false),
239     m_system_arch_set_while_connected (false),
240     m_sdk_sysroot (),
241     m_sdk_build (),
242     m_working_dir (),
243     m_remote_url (),
244     m_name (),
245     m_major_os_version (UINT32_MAX),
246     m_minor_os_version (UINT32_MAX),
247     m_update_os_version (UINT32_MAX),
248     m_system_arch(),
249     m_uid_map_mutex (Mutex::eMutexTypeNormal),
250     m_gid_map_mutex (Mutex::eMutexTypeNormal),
251     m_uid_map(),
252     m_gid_map(),
253     m_max_uid_name_len (0),
254     m_max_gid_name_len (0),
255     m_supports_rsync (false),
256     m_rsync_opts (),
257     m_rsync_prefix (),
258     m_supports_ssh (false),
259     m_ssh_opts (),
260     m_ignores_remote_hostname (false),
261     m_trap_handlers(),
262     m_calculated_trap_handlers (false),
263     m_trap_handler_mutex()
264 {
265     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
266     if (log)
267         log->Printf ("%p Platform::Platform()", static_cast<void*>(this));
268 }
269 
270 //------------------------------------------------------------------
271 /// Destructor.
272 ///
273 /// The destructor is virtual since this class is designed to be
274 /// inherited from by the plug-in instance.
275 //------------------------------------------------------------------
276 Platform::~Platform()
277 {
278     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
279     if (log)
280         log->Printf ("%p Platform::~Platform()", static_cast<void*>(this));
281 }
282 
283 void
284 Platform::GetStatus (Stream &strm)
285 {
286     uint32_t major = UINT32_MAX;
287     uint32_t minor = UINT32_MAX;
288     uint32_t update = UINT32_MAX;
289     std::string s;
290     strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
291 
292     ArchSpec arch (GetSystemArchitecture());
293     if (arch.IsValid())
294     {
295         if (!arch.GetTriple().str().empty())
296         strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
297     }
298 
299     if (GetOSVersion(major, minor, update))
300     {
301         strm.Printf("OS Version: %u", major);
302         if (minor != UINT32_MAX)
303             strm.Printf(".%u", minor);
304         if (update != UINT32_MAX)
305             strm.Printf(".%u", update);
306 
307         if (GetOSBuildString (s))
308             strm.Printf(" (%s)", s.c_str());
309 
310         strm.EOL();
311     }
312 
313     if (GetOSKernelDescription (s))
314         strm.Printf("    Kernel: %s\n", s.c_str());
315 
316     if (IsHost())
317     {
318         strm.Printf("  Hostname: %s\n", GetHostname());
319     }
320     else
321     {
322         const bool is_connected = IsConnected();
323         if (is_connected)
324             strm.Printf("  Hostname: %s\n", GetHostname());
325         strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
326     }
327 
328     if (GetWorkingDirectory())
329     {
330         strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString());
331     }
332     if (!IsConnected())
333         return;
334 
335     std::string specific_info(GetPlatformSpecificConnectionInformation());
336 
337     if (specific_info.empty() == false)
338         strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
339 }
340 
341 
342 bool
343 Platform::GetOSVersion (uint32_t &major,
344                         uint32_t &minor,
345                         uint32_t &update)
346 {
347     bool success = m_major_os_version != UINT32_MAX;
348     if (IsHost())
349     {
350         if (!success)
351         {
352             // We have a local host platform
353             success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, m_update_os_version);
354             m_os_version_set_while_connected = success;
355         }
356     }
357     else
358     {
359         // We have a remote platform. We can only fetch the remote
360         // OS version if we are connected, and we don't want to do it
361         // more than once.
362 
363         const bool is_connected = IsConnected();
364 
365         bool fetch = false;
366         if (success)
367         {
368             // We have valid OS version info, check to make sure it wasn't
369             // manually set prior to connecting. If it was manually set prior
370             // to connecting, then lets fetch the actual OS version info
371             // if we are now connected.
372             if (is_connected && !m_os_version_set_while_connected)
373                 fetch = true;
374         }
375         else
376         {
377             // We don't have valid OS version info, fetch it if we are connected
378             fetch = is_connected;
379         }
380 
381         if (fetch)
382         {
383             success = GetRemoteOSVersion ();
384             m_os_version_set_while_connected = success;
385         }
386     }
387 
388     if (success)
389     {
390         major = m_major_os_version;
391         minor = m_minor_os_version;
392         update = m_update_os_version;
393     }
394     return success;
395 }
396 
397 bool
398 Platform::GetOSBuildString (std::string &s)
399 {
400     s.clear();
401 
402     if (IsHost())
403 #if !defined(__linux__)
404         return HostInfo::GetOSBuildString(s);
405 #else
406         return false;
407 #endif
408     else
409         return GetRemoteOSBuildString (s);
410 }
411 
412 bool
413 Platform::GetOSKernelDescription (std::string &s)
414 {
415     if (IsHost())
416 #if !defined(__linux__)
417         return HostInfo::GetOSKernelDescription(s);
418 #else
419         return false;
420 #endif
421     else
422         return GetRemoteOSKernelDescription (s);
423 }
424 
425 ConstString
426 Platform::GetWorkingDirectory ()
427 {
428     if (IsHost())
429     {
430         char cwd[PATH_MAX];
431         if (getcwd(cwd, sizeof(cwd)))
432             return ConstString(cwd);
433         else
434             return ConstString();
435     }
436     else
437     {
438         if (!m_working_dir)
439             m_working_dir = GetRemoteWorkingDirectory();
440         return m_working_dir;
441     }
442 }
443 
444 
445 struct RecurseCopyBaton
446 {
447     const FileSpec& dst;
448     Platform *platform_ptr;
449     Error error;
450 };
451 
452 
453 static FileSpec::EnumerateDirectoryResult
454 RecurseCopy_Callback (void *baton,
455                       FileSpec::FileType file_type,
456                       const FileSpec &src)
457 {
458     RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
459     switch (file_type)
460     {
461         case FileSpec::eFileTypePipe:
462         case FileSpec::eFileTypeSocket:
463             // we have no way to copy pipes and sockets - ignore them and continue
464             return FileSpec::eEnumerateDirectoryResultNext;
465             break;
466 
467         case FileSpec::eFileTypeDirectory:
468             {
469                 // make the new directory and get in there
470                 FileSpec dst_dir = rc_baton->dst;
471                 if (!dst_dir.GetFilename())
472                     dst_dir.GetFilename() = src.GetLastPathComponent();
473                 std::string dst_dir_path (dst_dir.GetPath());
474                 Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
475                 if (error.Fail())
476                 {
477                     rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
478                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
479                 }
480 
481                 // now recurse
482                 std::string src_dir_path (src.GetPath());
483 
484                 // Make a filespec that only fills in the directory of a FileSpec so
485                 // when we enumerate we can quickly fill in the filename for dst copies
486                 FileSpec recurse_dst;
487                 recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
488                 RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() };
489                 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
490                 if (rc_baton2.error.Fail())
491                 {
492                     rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
493                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
494                 }
495                 return FileSpec::eEnumerateDirectoryResultNext;
496             }
497             break;
498 
499         case FileSpec::eFileTypeSymbolicLink:
500             {
501                 // copy the file and keep going
502                 FileSpec dst_file = rc_baton->dst;
503                 if (!dst_file.GetFilename())
504                     dst_file.GetFilename() = src.GetFilename();
505 
506                 char buf[PATH_MAX];
507 
508                 rc_baton->error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
509 
510                 if (rc_baton->error.Fail())
511                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
512 
513                 rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);
514 
515                 if (rc_baton->error.Fail())
516                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
517 
518                 return FileSpec::eEnumerateDirectoryResultNext;
519             }
520             break;
521         case FileSpec::eFileTypeRegular:
522             {
523                 // copy the file and keep going
524                 FileSpec dst_file = rc_baton->dst;
525                 if (!dst_file.GetFilename())
526                     dst_file.GetFilename() = src.GetFilename();
527                 Error err = rc_baton->platform_ptr->PutFile(src, dst_file);
528                 if (err.Fail())
529                 {
530                     rc_baton->error.SetErrorString(err.AsCString());
531                     return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
532                 }
533                 return FileSpec::eEnumerateDirectoryResultNext;
534             }
535             break;
536 
537         case FileSpec::eFileTypeInvalid:
538         case FileSpec::eFileTypeOther:
539         case FileSpec::eFileTypeUnknown:
540         default:
541             rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
542             return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
543             break;
544     }
545 }
546 
547 Error
548 Platform::Install (const FileSpec& src, const FileSpec& dst)
549 {
550     Error error;
551 
552     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
553     if (log)
554         log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str());
555     FileSpec fixed_dst(dst);
556 
557     if (!fixed_dst.GetFilename())
558         fixed_dst.GetFilename() = src.GetFilename();
559 
560     ConstString working_dir = GetWorkingDirectory();
561 
562     if (dst)
563     {
564         if (dst.GetDirectory())
565         {
566             const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
567             if (first_dst_dir_char == '/' || first_dst_dir_char  == '\\')
568             {
569                 fixed_dst.GetDirectory() = dst.GetDirectory();
570             }
571             // If the fixed destination file doesn't have a directory yet,
572             // then we must have a relative path. We will resolve this relative
573             // path against the platform's working directory
574             if (!fixed_dst.GetDirectory())
575             {
576                 FileSpec relative_spec;
577                 std::string path;
578                 if (working_dir)
579                 {
580                     relative_spec.SetFile(working_dir.GetCString(), false);
581                     relative_spec.AppendPathComponent(dst.GetPath().c_str());
582                     fixed_dst.GetDirectory() = relative_spec.GetDirectory();
583                 }
584                 else
585                 {
586                     error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
587                     return error;
588                 }
589             }
590         }
591         else
592         {
593             if (working_dir)
594             {
595                 fixed_dst.GetDirectory() = working_dir;
596             }
597             else
598             {
599                 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
600                 return error;
601             }
602         }
603     }
604     else
605     {
606         if (working_dir)
607         {
608             fixed_dst.GetDirectory() = working_dir;
609         }
610         else
611         {
612             error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty");
613             return error;
614         }
615     }
616 
617     if (log)
618         log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str());
619 
620     if (GetSupportsRSync())
621     {
622         error = PutFile(src, dst);
623     }
624     else
625     {
626         switch (src.GetFileType())
627         {
628             case FileSpec::eFileTypeDirectory:
629                 {
630                     if (GetFileExists (fixed_dst))
631                         Unlink (fixed_dst.GetPath().c_str());
632                     uint32_t permissions = src.GetPermissions();
633                     if (permissions == 0)
634                         permissions = eFilePermissionsDirectoryDefault;
635                     std::string dst_dir_path(fixed_dst.GetPath());
636                     error = MakeDirectory(dst_dir_path.c_str(), permissions);
637                     if (error.Success())
638                     {
639                         // Make a filespec that only fills in the directory of a FileSpec so
640                         // when we enumerate we can quickly fill in the filename for dst copies
641                         FileSpec recurse_dst;
642                         recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
643                         std::string src_dir_path (src.GetPath());
644                         RecurseCopyBaton baton = { recurse_dst, this, Error() };
645                         FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
646                         return baton.error;
647                     }
648                 }
649                 break;
650 
651             case FileSpec::eFileTypeRegular:
652                 if (GetFileExists (fixed_dst))
653                     Unlink (fixed_dst.GetPath().c_str());
654                 error = PutFile(src, fixed_dst);
655                 break;
656 
657             case FileSpec::eFileTypeSymbolicLink:
658                 {
659                     if (GetFileExists (fixed_dst))
660                         Unlink (fixed_dst.GetPath().c_str());
661                     char buf[PATH_MAX];
662                     error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
663                     if (error.Success())
664                         error = CreateSymlink(dst.GetPath().c_str(), buf);
665                 }
666                 break;
667             case FileSpec::eFileTypePipe:
668                 error.SetErrorString("platform install doesn't handle pipes");
669                 break;
670             case FileSpec::eFileTypeSocket:
671                 error.SetErrorString("platform install doesn't handle sockets");
672                 break;
673             case FileSpec::eFileTypeInvalid:
674             case FileSpec::eFileTypeUnknown:
675             case FileSpec::eFileTypeOther:
676                 error.SetErrorString("platform install doesn't handle non file or directory items");
677                 break;
678         }
679     }
680     return error;
681 }
682 
683 bool
684 Platform::SetWorkingDirectory (const ConstString &path)
685 {
686     if (IsHost())
687     {
688         Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
689         if (log)
690             log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString());
691 #ifdef _WIN32
692         // Not implemented on Windows
693         return false;
694 #else
695         if (path)
696         {
697             if (chdir(path.GetCString()) == 0)
698                 return true;
699         }
700         return false;
701 #endif
702     }
703     else
704     {
705         m_working_dir.Clear();
706         return SetRemoteWorkingDirectory(path);
707     }
708 }
709 
710 Error
711 Platform::MakeDirectory (const char *path, uint32_t permissions)
712 {
713     if (IsHost())
714         return FileSystem::MakeDirectory(path, permissions);
715     else
716     {
717         Error error;
718         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
719         return error;
720     }
721 }
722 
723 Error
724 Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
725 {
726     if (IsHost())
727         return FileSystem::GetFilePermissions(path, file_permissions);
728     else
729     {
730         Error error;
731         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
732         return error;
733     }
734 }
735 
736 Error
737 Platform::SetFilePermissions (const char *path, uint32_t file_permissions)
738 {
739     if (IsHost())
740         return FileSystem::SetFilePermissions(path, file_permissions);
741     else
742     {
743         Error error;
744         error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
745         return error;
746     }
747 }
748 
749 ConstString
750 Platform::GetName ()
751 {
752     return GetPluginName();
753 }
754 
755 const char *
756 Platform::GetHostname ()
757 {
758     if (IsHost())
759         return "127.0.0.1";
760 
761     if (m_name.empty())
762         return NULL;
763     return m_name.c_str();
764 }
765 
766 bool
767 Platform::SetRemoteWorkingDirectory(const ConstString &path)
768 {
769     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
770     if (log)
771         log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString());
772     m_working_dir = path;
773     return true;
774 }
775 
776 const char *
777 Platform::GetUserName (uint32_t uid)
778 {
779     const char *user_name = GetCachedUserName(uid);
780     if (user_name)
781         return user_name;
782     if (IsHost())
783     {
784         std::string name;
785         if (Host::GetUserName(uid, name))
786             return SetCachedUserName (uid, name.c_str(), name.size());
787     }
788     return NULL;
789 }
790 
791 const char *
792 Platform::GetGroupName (uint32_t gid)
793 {
794     const char *group_name = GetCachedGroupName(gid);
795     if (group_name)
796         return group_name;
797     if (IsHost())
798     {
799         std::string name;
800         if (Host::GetGroupName(gid, name))
801             return SetCachedGroupName (gid, name.c_str(), name.size());
802     }
803     return NULL;
804 }
805 
806 bool
807 Platform::SetOSVersion (uint32_t major,
808                         uint32_t minor,
809                         uint32_t update)
810 {
811     if (IsHost())
812     {
813         // We don't need anyone setting the OS version for the host platform,
814         // we should be able to figure it out by calling HostInfo::GetOSVersion(...).
815         return false;
816     }
817     else
818     {
819         // We have a remote platform, allow setting the target OS version if
820         // we aren't connected, since if we are connected, we should be able to
821         // request the remote OS version from the connected platform.
822         if (IsConnected())
823             return false;
824         else
825         {
826             // We aren't connected and we might want to set the OS version
827             // ahead of time before we connect so we can peruse files and
828             // use a local SDK or PDK cache of support files to disassemble
829             // or do other things.
830             m_major_os_version = major;
831             m_minor_os_version = minor;
832             m_update_os_version = update;
833             return true;
834         }
835     }
836     return false;
837 }
838 
839 
840 Error
841 Platform::ResolveExecutable (const FileSpec &exe_file,
842                              const ArchSpec &exe_arch,
843                              lldb::ModuleSP &exe_module_sp,
844                              const FileSpecList *module_search_paths_ptr)
845 {
846     Error error;
847     if (exe_file.Exists())
848     {
849         ModuleSpec module_spec (exe_file, exe_arch);
850         if (module_spec.GetArchitecture().IsValid())
851         {
852             error = ModuleList::GetSharedModule (module_spec,
853                                                  exe_module_sp,
854                                                  module_search_paths_ptr,
855                                                  NULL,
856                                                  NULL);
857         }
858         else
859         {
860             // No valid architecture was specified, ask the platform for
861             // the architectures that we should be using (in the correct order)
862             // and see if we can find a match that way
863             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
864             {
865                 error = ModuleList::GetSharedModule (module_spec,
866                                                      exe_module_sp,
867                                                      module_search_paths_ptr,
868                                                      NULL,
869                                                      NULL);
870                 // Did we find an executable using one of the
871                 if (error.Success() && exe_module_sp)
872                     break;
873             }
874         }
875     }
876     else
877     {
878         error.SetErrorStringWithFormat ("'%s' does not exist",
879                                         exe_file.GetPath().c_str());
880     }
881     return error;
882 }
883 
884 Error
885 Platform::ResolveSymbolFile (Target &target,
886                              const ModuleSpec &sym_spec,
887                              FileSpec &sym_file)
888 {
889     Error error;
890     if (sym_spec.GetSymbolFileSpec().Exists())
891         sym_file = sym_spec.GetSymbolFileSpec();
892     else
893         error.SetErrorString("unable to resolve symbol file");
894     return error;
895 
896 }
897 
898 
899 
900 bool
901 Platform::ResolveRemotePath (const FileSpec &platform_path,
902                              FileSpec &resolved_platform_path)
903 {
904     resolved_platform_path = platform_path;
905     return resolved_platform_path.ResolvePath();
906 }
907 
908 
909 const ArchSpec &
910 Platform::GetSystemArchitecture()
911 {
912     if (IsHost())
913     {
914         if (!m_system_arch.IsValid())
915         {
916             // We have a local host platform
917             m_system_arch = Host::GetArchitecture();
918             m_system_arch_set_while_connected = m_system_arch.IsValid();
919         }
920     }
921     else
922     {
923         // We have a remote platform. We can only fetch the remote
924         // system architecture if we are connected, and we don't want to do it
925         // more than once.
926 
927         const bool is_connected = IsConnected();
928 
929         bool fetch = false;
930         if (m_system_arch.IsValid())
931         {
932             // We have valid OS version info, check to make sure it wasn't
933             // manually set prior to connecting. If it was manually set prior
934             // to connecting, then lets fetch the actual OS version info
935             // if we are now connected.
936             if (is_connected && !m_system_arch_set_while_connected)
937                 fetch = true;
938         }
939         else
940         {
941             // We don't have valid OS version info, fetch it if we are connected
942             fetch = is_connected;
943         }
944 
945         if (fetch)
946         {
947             m_system_arch = GetRemoteSystemArchitecture ();
948             m_system_arch_set_while_connected = m_system_arch.IsValid();
949         }
950     }
951     return m_system_arch;
952 }
953 
954 
955 Error
956 Platform::ConnectRemote (Args& args)
957 {
958     Error error;
959     if (IsHost())
960         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
961     else
962         error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
963     return error;
964 }
965 
966 Error
967 Platform::DisconnectRemote ()
968 {
969     Error error;
970     if (IsHost())
971         error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
972     else
973         error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
974     return error;
975 }
976 
977 bool
978 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
979 {
980     // Take care of the host case so that each subclass can just
981     // call this function to get the host functionality.
982     if (IsHost())
983         return Host::GetProcessInfo (pid, process_info);
984     return false;
985 }
986 
987 uint32_t
988 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
989                          ProcessInstanceInfoList &process_infos)
990 {
991     // Take care of the host case so that each subclass can just
992     // call this function to get the host functionality.
993     uint32_t match_count = 0;
994     if (IsHost())
995         match_count = Host::FindProcesses (match_info, process_infos);
996     return match_count;
997 }
998 
999 
1000 Error
1001 Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
1002 {
1003     Error error;
1004     // Take care of the host case so that each subclass can just
1005     // call this function to get the host functionality.
1006     if (IsHost())
1007     {
1008         if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
1009             launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
1010 
1011         if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
1012         {
1013             const bool is_localhost = true;
1014             const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
1015             const bool first_arg_is_full_shell_command = false;
1016             uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
1017             if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
1018                                                                   is_localhost,
1019                                                                   will_debug,
1020                                                                   first_arg_is_full_shell_command,
1021                                                                   num_resumes))
1022                 return error;
1023         }
1024 
1025         error = Host::LaunchProcess (launch_info);
1026     }
1027     else
1028         error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
1029     return error;
1030 }
1031 
1032 lldb::ProcessSP
1033 Platform::DebugProcess (ProcessLaunchInfo &launch_info,
1034                         Debugger &debugger,
1035                         Target *target,       // Can be NULL, if NULL create a new target, else use existing one
1036                         Listener &listener,
1037                         Error &error)
1038 {
1039     ProcessSP process_sp;
1040     // Make sure we stop at the entry point
1041     launch_info.GetFlags ().Set (eLaunchFlagDebug);
1042     // We always launch the process we are going to debug in a separate process
1043     // group, since then we can handle ^C interrupts ourselves w/o having to worry
1044     // about the target getting them as well.
1045     launch_info.SetLaunchInSeparateProcessGroup(true);
1046 
1047     error = LaunchProcess (launch_info);
1048     if (error.Success())
1049     {
1050         if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1051         {
1052             ProcessAttachInfo attach_info (launch_info);
1053             process_sp = Attach (attach_info, debugger, target, listener, error);
1054             if (process_sp)
1055             {
1056                 launch_info.SetHijackListener(attach_info.GetHijackListener());
1057 
1058                 // Since we attached to the process, it will think it needs to detach
1059                 // if the process object just goes away without an explicit call to
1060                 // Process::Kill() or Process::Detach(), so let it know to kill the
1061                 // process if this happens.
1062                 process_sp->SetShouldDetach (false);
1063 
1064                 // If we didn't have any file actions, the pseudo terminal might
1065                 // have been used where the slave side was given as the file to
1066                 // open for stdin/out/err after we have already opened the master
1067                 // so we can read/write stdin/out/err.
1068                 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
1069                 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
1070                 {
1071                     process_sp->SetSTDIOFileDescriptor(pty_fd);
1072                 }
1073             }
1074         }
1075     }
1076     return process_sp;
1077 }
1078 
1079 
1080 lldb::PlatformSP
1081 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
1082 {
1083     lldb::PlatformSP platform_sp;
1084     Error error;
1085     if (arch.IsValid())
1086         platform_sp = Platform::Create (arch, platform_arch_ptr, error);
1087     return platform_sp;
1088 }
1089 
1090 
1091 //------------------------------------------------------------------
1092 /// Lets a platform answer if it is compatible with a given
1093 /// architecture and the target triple contained within.
1094 //------------------------------------------------------------------
1095 bool
1096 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
1097 {
1098     // If the architecture is invalid, we must answer true...
1099     if (arch.IsValid())
1100     {
1101         ArchSpec platform_arch;
1102         // Try for an exact architecture match first.
1103         if (exact_arch_match)
1104         {
1105             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1106             {
1107                 if (arch.IsExactMatch(platform_arch))
1108                 {
1109                     if (compatible_arch_ptr)
1110                         *compatible_arch_ptr = platform_arch;
1111                     return true;
1112                 }
1113             }
1114         }
1115         else
1116         {
1117             for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1118             {
1119                 if (arch.IsCompatibleMatch(platform_arch))
1120                 {
1121                     if (compatible_arch_ptr)
1122                         *compatible_arch_ptr = platform_arch;
1123                     return true;
1124                 }
1125             }
1126         }
1127     }
1128     if (compatible_arch_ptr)
1129         compatible_arch_ptr->Clear();
1130     return false;
1131 }
1132 
1133 Error
1134 Platform::PutFile (const FileSpec& source,
1135                    const FileSpec& destination,
1136                    uint32_t uid,
1137                    uint32_t gid)
1138 {
1139     Error error("unimplemented");
1140     return error;
1141 }
1142 
1143 Error
1144 Platform::GetFile (const FileSpec& source,
1145                    const FileSpec& destination)
1146 {
1147     Error error("unimplemented");
1148     return error;
1149 }
1150 
1151 Error
1152 Platform::CreateSymlink (const char *src, // The name of the link is in src
1153                          const char *dst)// The symlink points to dst
1154 {
1155     Error error("unimplemented");
1156     return error;
1157 }
1158 
1159 bool
1160 Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
1161 {
1162     return false;
1163 }
1164 
1165 Error
1166 Platform::Unlink (const char *path)
1167 {
1168     Error error("unimplemented");
1169     return error;
1170 }
1171 
1172 
1173 
1174 lldb_private::Error
1175 Platform::RunShellCommand (const char *command,           // Shouldn't be NULL
1176                            const char *working_dir,       // Pass NULL to use the current working directory
1177                            int *status_ptr,               // Pass NULL if you don't want the process exit status
1178                            int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
1179                            std::string *command_output,   // Pass NULL if you don't want the command output
1180                            uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
1181 {
1182     if (IsHost())
1183         return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
1184     else
1185         return Error("unimplemented");
1186 }
1187 
1188 
1189 bool
1190 Platform::CalculateMD5 (const FileSpec& file_spec,
1191                         uint64_t &low,
1192                         uint64_t &high)
1193 {
1194     if (IsHost())
1195         return FileSystem::CalculateMD5(file_spec, low, high);
1196     else
1197         return false;
1198 }
1199 
1200 Error
1201 Platform::LaunchNativeProcess (
1202     ProcessLaunchInfo &launch_info,
1203     lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
1204     NativeProcessProtocolSP &process_sp)
1205 {
1206     // Platforms should override this implementation if they want to
1207     // support lldb-gdbserver.
1208     return Error("unimplemented");
1209 }
1210 
1211 Error
1212 Platform::AttachNativeProcess (lldb::pid_t pid,
1213                                lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
1214                                NativeProcessProtocolSP &process_sp)
1215 {
1216     // Platforms should override this implementation if they want to
1217     // support lldb-gdbserver.
1218     return Error("unimplemented");
1219 }
1220 
1221 void
1222 Platform::SetLocalCacheDirectory (const char* local)
1223 {
1224     m_local_cache_directory.assign(local);
1225 }
1226 
1227 const char*
1228 Platform::GetLocalCacheDirectory ()
1229 {
1230     return m_local_cache_directory.c_str();
1231 }
1232 
1233 static OptionDefinition
1234 g_rsync_option_table[] =
1235 {
1236     {   LLDB_OPT_SET_ALL, false, "rsync"                  , 'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Enable rsync." },
1237     {   LLDB_OPT_SET_ALL, false, "rsync-opts"             , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for rsync to work." },
1238     {   LLDB_OPT_SET_ALL, false, "rsync-prefix"           , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific rsync prefix put before the remote path." },
1239     {   LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Do not automatically fill in the remote hostname when composing the rsync command." },
1240 };
1241 
1242 static OptionDefinition
1243 g_ssh_option_table[] =
1244 {
1245     {   LLDB_OPT_SET_ALL, false, "ssh"                    , 's', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Enable SSH." },
1246     {   LLDB_OPT_SET_ALL, false, "ssh-opts"               , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for SSH to work." },
1247 };
1248 
1249 static OptionDefinition
1250 g_caching_option_table[] =
1251 {
1252     {   LLDB_OPT_SET_ALL, false, "local-cache-dir"        , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath         , "Path in which to store local copies of files." },
1253 };
1254 
1255 OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
1256 {
1257 }
1258 
1259 OptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
1260 {
1261 }
1262 
1263 const lldb_private::OptionDefinition*
1264 OptionGroupPlatformRSync::GetDefinitions ()
1265 {
1266     return g_rsync_option_table;
1267 }
1268 
1269 void
1270 OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
1271 {
1272     m_rsync = false;
1273     m_rsync_opts.clear();
1274     m_rsync_prefix.clear();
1275     m_ignores_remote_hostname = false;
1276 }
1277 
1278 lldb_private::Error
1279 OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
1280                 uint32_t option_idx,
1281                 const char *option_arg)
1282 {
1283     Error error;
1284     char short_option = (char) GetDefinitions()[option_idx].short_option;
1285     switch (short_option)
1286     {
1287         case 'r':
1288             m_rsync = true;
1289             break;
1290 
1291         case 'R':
1292             m_rsync_opts.assign(option_arg);
1293             break;
1294 
1295         case 'P':
1296             m_rsync_prefix.assign(option_arg);
1297             break;
1298 
1299         case 'i':
1300             m_ignores_remote_hostname = true;
1301             break;
1302 
1303         default:
1304             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1305             break;
1306     }
1307 
1308     return error;
1309 }
1310 
1311 uint32_t
1312 OptionGroupPlatformRSync::GetNumDefinitions ()
1313 {
1314     return llvm::array_lengthof(g_rsync_option_table);
1315 }
1316 
1317 lldb::BreakpointSP
1318 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
1319 {
1320     return lldb::BreakpointSP();
1321 }
1322 
1323 OptionGroupPlatformSSH::OptionGroupPlatformSSH ()
1324 {
1325 }
1326 
1327 OptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
1328 {
1329 }
1330 
1331 const lldb_private::OptionDefinition*
1332 OptionGroupPlatformSSH::GetDefinitions ()
1333 {
1334     return g_ssh_option_table;
1335 }
1336 
1337 void
1338 OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
1339 {
1340     m_ssh = false;
1341     m_ssh_opts.clear();
1342 }
1343 
1344 lldb_private::Error
1345 OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
1346                                           uint32_t option_idx,
1347                                           const char *option_arg)
1348 {
1349     Error error;
1350     char short_option = (char) GetDefinitions()[option_idx].short_option;
1351     switch (short_option)
1352     {
1353         case 's':
1354             m_ssh = true;
1355             break;
1356 
1357         case 'S':
1358             m_ssh_opts.assign(option_arg);
1359             break;
1360 
1361         default:
1362             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1363             break;
1364     }
1365 
1366     return error;
1367 }
1368 
1369 uint32_t
1370 OptionGroupPlatformSSH::GetNumDefinitions ()
1371 {
1372     return llvm::array_lengthof(g_ssh_option_table);
1373 }
1374 
1375 OptionGroupPlatformCaching::OptionGroupPlatformCaching ()
1376 {
1377 }
1378 
1379 OptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
1380 {
1381 }
1382 
1383 const lldb_private::OptionDefinition*
1384 OptionGroupPlatformCaching::GetDefinitions ()
1385 {
1386     return g_caching_option_table;
1387 }
1388 
1389 void
1390 OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
1391 {
1392     m_cache_dir.clear();
1393 }
1394 
1395 lldb_private::Error
1396 OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
1397                                         uint32_t option_idx,
1398                                         const char *option_arg)
1399 {
1400     Error error;
1401     char short_option = (char) GetDefinitions()[option_idx].short_option;
1402     switch (short_option)
1403     {
1404         case 'c':
1405             m_cache_dir.assign(option_arg);
1406             break;
1407 
1408         default:
1409             error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1410             break;
1411     }
1412 
1413     return error;
1414 }
1415 
1416 uint32_t
1417 OptionGroupPlatformCaching::GetNumDefinitions ()
1418 {
1419     return llvm::array_lengthof(g_caching_option_table);
1420 }
1421 
1422 size_t
1423 Platform::GetEnvironment (StringList &environment)
1424 {
1425     environment.Clear();
1426     return false;
1427 }
1428 
1429 const std::vector<ConstString> &
1430 Platform::GetTrapHandlerSymbolNames ()
1431 {
1432     if (!m_calculated_trap_handlers)
1433     {
1434         Mutex::Locker locker (m_trap_handler_mutex);
1435         if (!m_calculated_trap_handlers)
1436         {
1437             CalculateTrapHandlerSymbolNames();
1438             m_calculated_trap_handlers = true;
1439         }
1440     }
1441     return m_trap_handlers;
1442 }
1443 
1444