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