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