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