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