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