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