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