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