Platform.cpp revision 263363
1//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Target/Platform.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Breakpoint/BreakpointIDList.h"
17#include "lldb/Core/Error.h"
18#include "lldb/Core/Log.h"
19#include "lldb/Core/ModuleSpec.h"
20#include "lldb/Core/PluginManager.h"
21#include "lldb/Host/FileSpec.h"
22#include "lldb/Host/Host.h"
23#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Utility/Utils.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30// Use a singleton function for g_local_platform_sp to avoid init
31// constructors since LLDB is often part of a shared library
32static PlatformSP&
33GetDefaultPlatformSP ()
34{
35    static PlatformSP g_default_platform_sp;
36    return g_default_platform_sp;
37}
38
39static Mutex &
40GetConnectedPlatformListMutex ()
41{
42    static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
43    return g_remote_connected_platforms_mutex;
44}
45static std::vector<PlatformSP> &
46GetConnectedPlatformList ()
47{
48    static std::vector<PlatformSP> g_remote_connected_platforms;
49    return g_remote_connected_platforms;
50}
51
52
53const char *
54Platform::GetHostPlatformName ()
55{
56    return "host";
57}
58
59//------------------------------------------------------------------
60/// Get the native host platform plug-in.
61///
62/// There should only be one of these for each host that LLDB runs
63/// upon that should be statically compiled in and registered using
64/// preprocessor macros or other similar build mechanisms.
65///
66/// This platform will be used as the default platform when launching
67/// or attaching to processes unless another platform is specified.
68//------------------------------------------------------------------
69PlatformSP
70Platform::GetDefaultPlatform ()
71{
72    return GetDefaultPlatformSP ();
73}
74
75void
76Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
77{
78    // The native platform should use its static void Platform::Initialize()
79    // function to register itself as the native platform.
80    GetDefaultPlatformSP () = platform_sp;
81}
82
83Error
84Platform::GetFile (const FileSpec &platform_file,
85                   const UUID *uuid_ptr,
86                   FileSpec &local_file)
87{
88    // Default to the local case
89    local_file = platform_file;
90    return Error();
91}
92
93FileSpecList
94Platform::LocateExecutableScriptingResources (Target *target, Module &module)
95{
96    return FileSpecList();
97}
98
99Platform*
100Platform::FindPlugin (Process *process, const ConstString &plugin_name)
101{
102    PlatformCreateInstance create_callback = NULL;
103    if (plugin_name)
104    {
105        create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
106        if (create_callback)
107        {
108            ArchSpec arch;
109            if (process)
110            {
111                arch = process->GetTarget().GetArchitecture();
112            }
113            std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
114            if (instance_ap.get())
115                return instance_ap.release();
116        }
117    }
118    else
119    {
120        for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
121        {
122            std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
123            if (instance_ap.get())
124                return instance_ap.release();
125        }
126    }
127    return NULL;
128}
129
130Error
131Platform::GetSharedModule (const ModuleSpec &module_spec,
132                           ModuleSP &module_sp,
133                           const FileSpecList *module_search_paths_ptr,
134                           ModuleSP *old_module_sp_ptr,
135                           bool *did_create_ptr)
136{
137    // Don't do any path remapping for the default implementation
138    // of the platform GetSharedModule function, just call through
139    // to our static ModuleList function. Platform subclasses that
140    // implement remote debugging, might have a developer kits
141    // installed that have cached versions of the files for the
142    // remote target, or might implement a download and cache
143    // locally implementation.
144    const bool always_create = false;
145    return ModuleList::GetSharedModule (module_spec,
146                                        module_sp,
147                                        module_search_paths_ptr,
148                                        old_module_sp_ptr,
149                                        did_create_ptr,
150                                        always_create);
151}
152
153PlatformSP
154Platform::Create (const char *platform_name, Error &error)
155{
156    PlatformCreateInstance create_callback = NULL;
157    lldb::PlatformSP platform_sp;
158    if (platform_name && platform_name[0])
159    {
160        ConstString const_platform_name (platform_name);
161        create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
162        if (create_callback)
163            platform_sp.reset(create_callback(true, NULL));
164        else
165            error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
166    }
167    else
168        error.SetErrorString ("invalid platform name");
169    return platform_sp;
170}
171
172
173PlatformSP
174Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
175{
176    lldb::PlatformSP platform_sp;
177    if (arch.IsValid())
178    {
179        uint32_t idx;
180        PlatformCreateInstance create_callback;
181        // First try exact arch matches across all platform plug-ins
182        bool exact = true;
183        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
184        {
185            if (create_callback)
186            {
187                platform_sp.reset(create_callback(false, &arch));
188                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
189                    return platform_sp;
190            }
191        }
192        // Next try compatible arch matches across all platform plug-ins
193        exact = false;
194        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
195        {
196            if (create_callback)
197            {
198                platform_sp.reset(create_callback(false, &arch));
199                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
200                    return platform_sp;
201            }
202        }
203    }
204    else
205        error.SetErrorString ("invalid platform name");
206    if (platform_arch_ptr)
207        platform_arch_ptr->Clear();
208    platform_sp.reset();
209    return platform_sp;
210}
211
212uint32_t
213Platform::GetNumConnectedRemotePlatforms ()
214{
215    Mutex::Locker locker (GetConnectedPlatformListMutex ());
216    return GetConnectedPlatformList().size();
217}
218
219PlatformSP
220Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
221{
222    PlatformSP platform_sp;
223    {
224        Mutex::Locker locker (GetConnectedPlatformListMutex ());
225        if (idx < GetConnectedPlatformList().size())
226            platform_sp = GetConnectedPlatformList ()[idx];
227    }
228    return platform_sp;
229}
230
231//------------------------------------------------------------------
232/// Default Constructor
233//------------------------------------------------------------------
234Platform::Platform (bool is_host) :
235    m_is_host (is_host),
236    m_os_version_set_while_connected (false),
237    m_system_arch_set_while_connected (false),
238    m_sdk_sysroot (),
239    m_sdk_build (),
240    m_remote_url (),
241    m_name (),
242    m_major_os_version (UINT32_MAX),
243    m_minor_os_version (UINT32_MAX),
244    m_update_os_version (UINT32_MAX),
245    m_system_arch(),
246    m_uid_map_mutex (Mutex::eMutexTypeNormal),
247    m_gid_map_mutex (Mutex::eMutexTypeNormal),
248    m_uid_map(),
249    m_gid_map(),
250    m_max_uid_name_len (0),
251    m_max_gid_name_len (0),
252    m_supports_rsync (false),
253    m_rsync_opts (),
254    m_rsync_prefix (),
255    m_supports_ssh (false),
256    m_ssh_opts (),
257    m_ignores_remote_hostname (false)
258{
259    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
260    if (log)
261        log->Printf ("%p Platform::Platform()", this);
262}
263
264//------------------------------------------------------------------
265/// Destructor.
266///
267/// The destructor is virtual since this class is designed to be
268/// inherited from by the plug-in instance.
269//------------------------------------------------------------------
270Platform::~Platform()
271{
272    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
273    if (log)
274        log->Printf ("%p Platform::~Platform()", this);
275}
276
277void
278Platform::GetStatus (Stream &strm)
279{
280    uint32_t major = UINT32_MAX;
281    uint32_t minor = UINT32_MAX;
282    uint32_t update = UINT32_MAX;
283    std::string s;
284    strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
285
286    ArchSpec arch (GetSystemArchitecture());
287    if (arch.IsValid())
288    {
289        if (!arch.GetTriple().str().empty())
290        strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
291    }
292
293    if (GetOSVersion(major, minor, update))
294    {
295        strm.Printf("OS Version: %u", major);
296        if (minor != UINT32_MAX)
297            strm.Printf(".%u", minor);
298        if (update != UINT32_MAX)
299            strm.Printf(".%u", update);
300
301        if (GetOSBuildString (s))
302            strm.Printf(" (%s)", s.c_str());
303
304        strm.EOL();
305    }
306
307    if (GetOSKernelDescription (s))
308        strm.Printf("    Kernel: %s\n", s.c_str());
309
310    if (IsHost())
311    {
312        strm.Printf("  Hostname: %s\n", GetHostname());
313    }
314    else
315    {
316        const bool is_connected = IsConnected();
317        if (is_connected)
318            strm.Printf("  Hostname: %s\n", GetHostname());
319        strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
320    }
321
322    if (!IsConnected())
323        return;
324
325    std::string specific_info(GetPlatformSpecificConnectionInformation());
326
327    if (specific_info.empty() == false)
328        strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
329}
330
331
332bool
333Platform::GetOSVersion (uint32_t &major,
334                        uint32_t &minor,
335                        uint32_t &update)
336{
337    bool success = m_major_os_version != UINT32_MAX;
338    if (IsHost())
339    {
340        if (!success)
341        {
342            // We have a local host platform
343            success = Host::GetOSVersion (m_major_os_version,
344                                          m_minor_os_version,
345                                          m_update_os_version);
346            m_os_version_set_while_connected = success;
347        }
348    }
349    else
350    {
351        // We have a remote platform. We can only fetch the remote
352        // OS version if we are connected, and we don't want to do it
353        // more than once.
354
355        const bool is_connected = IsConnected();
356
357        bool fetch = false;
358        if (success)
359        {
360            // We have valid OS version info, check to make sure it wasn't
361            // manually set prior to connecting. If it was manually set prior
362            // to connecting, then lets fetch the actual OS version info
363            // if we are now connected.
364            if (is_connected && !m_os_version_set_while_connected)
365                fetch = true;
366        }
367        else
368        {
369            // We don't have valid OS version info, fetch it if we are connected
370            fetch = is_connected;
371        }
372
373        if (fetch)
374        {
375            success = GetRemoteOSVersion ();
376            m_os_version_set_while_connected = success;
377        }
378    }
379
380    if (success)
381    {
382        major = m_major_os_version;
383        minor = m_minor_os_version;
384        update = m_update_os_version;
385    }
386    return success;
387}
388
389bool
390Platform::GetOSBuildString (std::string &s)
391{
392    if (IsHost())
393        return Host::GetOSBuildString (s);
394    else
395        return GetRemoteOSBuildString (s);
396}
397
398bool
399Platform::GetOSKernelDescription (std::string &s)
400{
401    if (IsHost())
402        return Host::GetOSKernelDescription (s);
403    else
404        return GetRemoteOSKernelDescription (s);
405}
406
407ConstString
408Platform::GetName ()
409{
410    const char *name = GetHostname();
411    if (name == NULL || name[0] == '\0')
412        return GetPluginName();
413    return ConstString (name);
414}
415
416const char *
417Platform::GetHostname ()
418{
419    if (IsHost())
420        return "localhost";
421
422    if (m_name.empty())
423        return NULL;
424    return m_name.c_str();
425}
426
427const char *
428Platform::GetUserName (uint32_t uid)
429{
430    const char *user_name = GetCachedUserName(uid);
431    if (user_name)
432        return user_name;
433    if (IsHost())
434    {
435        std::string name;
436        if (Host::GetUserName(uid, name))
437            return SetCachedUserName (uid, name.c_str(), name.size());
438    }
439    return NULL;
440}
441
442const char *
443Platform::GetGroupName (uint32_t gid)
444{
445    const char *group_name = GetCachedGroupName(gid);
446    if (group_name)
447        return group_name;
448    if (IsHost())
449    {
450        std::string name;
451        if (Host::GetGroupName(gid, name))
452            return SetCachedGroupName (gid, name.c_str(), name.size());
453    }
454    return NULL;
455}
456
457bool
458Platform::SetOSVersion (uint32_t major,
459                        uint32_t minor,
460                        uint32_t update)
461{
462    if (IsHost())
463    {
464        // We don't need anyone setting the OS version for the host platform,
465        // we should be able to figure it out by calling Host::GetOSVersion(...).
466        return false;
467    }
468    else
469    {
470        // We have a remote platform, allow setting the target OS version if
471        // we aren't connected, since if we are connected, we should be able to
472        // request the remote OS version from the connected platform.
473        if (IsConnected())
474            return false;
475        else
476        {
477            // We aren't connected and we might want to set the OS version
478            // ahead of time before we connect so we can peruse files and
479            // use a local SDK or PDK cache of support files to disassemble
480            // or do other things.
481            m_major_os_version = major;
482            m_minor_os_version = minor;
483            m_update_os_version = update;
484            return true;
485        }
486    }
487    return false;
488}
489
490
491Error
492Platform::ResolveExecutable (const FileSpec &exe_file,
493                             const ArchSpec &exe_arch,
494                             lldb::ModuleSP &exe_module_sp,
495                             const FileSpecList *module_search_paths_ptr)
496{
497    Error error;
498    if (exe_file.Exists())
499    {
500        ModuleSpec module_spec (exe_file, exe_arch);
501        if (module_spec.GetArchitecture().IsValid())
502        {
503            error = ModuleList::GetSharedModule (module_spec,
504                                                 exe_module_sp,
505                                                 module_search_paths_ptr,
506                                                 NULL,
507                                                 NULL);
508        }
509        else
510        {
511            // No valid architecture was specified, ask the platform for
512            // the architectures that we should be using (in the correct order)
513            // and see if we can find a match that way
514            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
515            {
516                error = ModuleList::GetSharedModule (module_spec,
517                                                     exe_module_sp,
518                                                     module_search_paths_ptr,
519                                                     NULL,
520                                                     NULL);
521                // Did we find an executable using one of the
522                if (error.Success() && exe_module_sp)
523                    break;
524            }
525        }
526    }
527    else
528    {
529        error.SetErrorStringWithFormat ("'%s' does not exist",
530                                        exe_file.GetPath().c_str());
531    }
532    return error;
533}
534
535Error
536Platform::ResolveSymbolFile (Target &target,
537                             const ModuleSpec &sym_spec,
538                             FileSpec &sym_file)
539{
540    Error error;
541    if (sym_spec.GetSymbolFileSpec().Exists())
542        sym_file = sym_spec.GetSymbolFileSpec();
543    else
544        error.SetErrorString("unable to resolve symbol file");
545    return error;
546
547}
548
549
550
551bool
552Platform::ResolveRemotePath (const FileSpec &platform_path,
553                             FileSpec &resolved_platform_path)
554{
555    resolved_platform_path = platform_path;
556    return resolved_platform_path.ResolvePath();
557}
558
559
560const ArchSpec &
561Platform::GetSystemArchitecture()
562{
563    if (IsHost())
564    {
565        if (!m_system_arch.IsValid())
566        {
567            // We have a local host platform
568            m_system_arch = Host::GetArchitecture();
569            m_system_arch_set_while_connected = m_system_arch.IsValid();
570        }
571    }
572    else
573    {
574        // We have a remote platform. We can only fetch the remote
575        // system architecture if we are connected, and we don't want to do it
576        // more than once.
577
578        const bool is_connected = IsConnected();
579
580        bool fetch = false;
581        if (m_system_arch.IsValid())
582        {
583            // We have valid OS version info, check to make sure it wasn't
584            // manually set prior to connecting. If it was manually set prior
585            // to connecting, then lets fetch the actual OS version info
586            // if we are now connected.
587            if (is_connected && !m_system_arch_set_while_connected)
588                fetch = true;
589        }
590        else
591        {
592            // We don't have valid OS version info, fetch it if we are connected
593            fetch = is_connected;
594        }
595
596        if (fetch)
597        {
598            m_system_arch = GetRemoteSystemArchitecture ();
599            m_system_arch_set_while_connected = m_system_arch.IsValid();
600        }
601    }
602    return m_system_arch;
603}
604
605
606Error
607Platform::ConnectRemote (Args& args)
608{
609    Error error;
610    if (IsHost())
611        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
612    else
613        error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
614    return error;
615}
616
617Error
618Platform::DisconnectRemote ()
619{
620    Error error;
621    if (IsHost())
622        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
623    else
624        error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
625    return error;
626}
627
628bool
629Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
630{
631    // Take care of the host case so that each subclass can just
632    // call this function to get the host functionality.
633    if (IsHost())
634        return Host::GetProcessInfo (pid, process_info);
635    return false;
636}
637
638uint32_t
639Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
640                         ProcessInstanceInfoList &process_infos)
641{
642    // Take care of the host case so that each subclass can just
643    // call this function to get the host functionality.
644    uint32_t match_count = 0;
645    if (IsHost())
646        match_count = Host::FindProcesses (match_info, process_infos);
647    return match_count;
648}
649
650
651Error
652Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
653{
654    Error error;
655    // Take care of the host case so that each subclass can just
656    // call this function to get the host functionality.
657    if (IsHost())
658    {
659        if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
660            launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
661
662        if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
663        {
664            const bool is_localhost = true;
665            const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
666            const bool first_arg_is_full_shell_command = false;
667            uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
668            if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
669                                                                  is_localhost,
670                                                                  will_debug,
671                                                                  first_arg_is_full_shell_command,
672                                                                  num_resumes))
673                return error;
674        }
675
676        error = Host::LaunchProcess (launch_info);
677    }
678    else
679        error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
680    return error;
681}
682
683lldb::ProcessSP
684Platform::DebugProcess (ProcessLaunchInfo &launch_info,
685                        Debugger &debugger,
686                        Target *target,       // Can be NULL, if NULL create a new target, else use existing one
687                        Listener &listener,
688                        Error &error)
689{
690    ProcessSP process_sp;
691    // Make sure we stop at the entry point
692    launch_info.GetFlags ().Set (eLaunchFlagDebug);
693    // We always launch the process we are going to debug in a separate process
694    // group, since then we can handle ^C interrupts ourselves w/o having to worry
695    // about the target getting them as well.
696    launch_info.SetLaunchInSeparateProcessGroup(true);
697
698    error = LaunchProcess (launch_info);
699    if (error.Success())
700    {
701        if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
702        {
703            ProcessAttachInfo attach_info (launch_info);
704            process_sp = Attach (attach_info, debugger, target, listener, error);
705            if (process_sp)
706            {
707                // Since we attached to the process, it will think it needs to detach
708                // if the process object just goes away without an explicit call to
709                // Process::Kill() or Process::Detach(), so let it know to kill the
710                // process if this happens.
711                process_sp->SetShouldDetach (false);
712
713                // If we didn't have any file actions, the pseudo terminal might
714                // have been used where the slave side was given as the file to
715                // open for stdin/out/err after we have already opened the master
716                // so we can read/write stdin/out/err.
717                int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
718                if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
719                {
720                    process_sp->SetSTDIOFileDescriptor(pty_fd);
721                }
722            }
723        }
724    }
725    return process_sp;
726}
727
728
729lldb::PlatformSP
730Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
731{
732    lldb::PlatformSP platform_sp;
733    Error error;
734    if (arch.IsValid())
735        platform_sp = Platform::Create (arch, platform_arch_ptr, error);
736    return platform_sp;
737}
738
739
740//------------------------------------------------------------------
741/// Lets a platform answer if it is compatible with a given
742/// architecture and the target triple contained within.
743//------------------------------------------------------------------
744bool
745Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
746{
747    // If the architecture is invalid, we must answer true...
748    if (arch.IsValid())
749    {
750        ArchSpec platform_arch;
751        // Try for an exact architecture match first.
752        if (exact_arch_match)
753        {
754            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
755            {
756                if (arch.IsExactMatch(platform_arch))
757                {
758                    if (compatible_arch_ptr)
759                        *compatible_arch_ptr = platform_arch;
760                    return true;
761                }
762            }
763        }
764        else
765        {
766            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
767            {
768                if (arch.IsCompatibleMatch(platform_arch))
769                {
770                    if (compatible_arch_ptr)
771                        *compatible_arch_ptr = platform_arch;
772                    return true;
773                }
774            }
775        }
776    }
777    if (compatible_arch_ptr)
778        compatible_arch_ptr->Clear();
779    return false;
780}
781
782uint32_t
783Platform::MakeDirectory (const FileSpec &spec,
784                         mode_t mode)
785{
786    std::string path(spec.GetPath());
787    return this->MakeDirectory(path,mode);
788}
789
790Error
791Platform::PutFile (const FileSpec& source,
792                   const FileSpec& destination,
793                   uint32_t uid,
794                   uint32_t gid)
795{
796    Error error("unimplemented");
797    return error;
798}
799
800Error
801Platform::GetFile (const FileSpec& source,
802                   const FileSpec& destination)
803{
804    Error error("unimplemented");
805    return error;
806}
807
808bool
809Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
810{
811    return false;
812}
813
814lldb_private::Error
815Platform::RunShellCommand (const char *command,           // Shouldn't be NULL
816                           const char *working_dir,       // Pass NULL to use the current working directory
817                           int *status_ptr,               // Pass NULL if you don't want the process exit status
818                           int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
819                           std::string *command_output,   // Pass NULL if you don't want the command output
820                           uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
821{
822    if (IsHost())
823        return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
824    else
825        return Error("unimplemented");
826}
827
828
829bool
830Platform::CalculateMD5 (const FileSpec& file_spec,
831                        uint64_t &low,
832                        uint64_t &high)
833{
834    if (IsHost())
835        return Host::CalculateMD5(file_spec, low, high);
836    else
837        return false;
838}
839
840void
841Platform::SetLocalCacheDirectory (const char* local)
842{
843    m_local_cache_directory.assign(local);
844}
845
846const char*
847Platform::GetLocalCacheDirectory ()
848{
849    return m_local_cache_directory.c_str();
850}
851
852static OptionDefinition
853g_rsync_option_table[] =
854{
855    {   LLDB_OPT_SET_ALL, false, "rsync"                  , 'r', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Enable rsync." },
856    {   LLDB_OPT_SET_ALL, false, "rsync-opts"             , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for rsync to work." },
857    {   LLDB_OPT_SET_ALL, false, "rsync-prefix"           , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific rsync prefix put before the remote path." },
858    {   LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Do not automatically fill in the remote hostname when composing the rsync command." },
859};
860
861static OptionDefinition
862g_ssh_option_table[] =
863{
864    {   LLDB_OPT_SET_ALL, false, "ssh"                    , 's', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Enable SSH." },
865    {   LLDB_OPT_SET_ALL, false, "ssh-opts"               , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for SSH to work." },
866};
867
868static OptionDefinition
869g_caching_option_table[] =
870{
871    {   LLDB_OPT_SET_ALL, false, "local-cache-dir"        , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath         , "Path in which to store local copies of files." },
872};
873
874OptionGroupPlatformRSync::OptionGroupPlatformRSync ()
875{
876}
877
878OptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
879{
880}
881
882const lldb_private::OptionDefinition*
883OptionGroupPlatformRSync::GetDefinitions ()
884{
885    return g_rsync_option_table;
886}
887
888void
889OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
890{
891    m_rsync = false;
892    m_rsync_opts.clear();
893    m_rsync_prefix.clear();
894    m_ignores_remote_hostname = false;
895}
896
897lldb_private::Error
898OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
899                uint32_t option_idx,
900                const char *option_arg)
901{
902    Error error;
903    char short_option = (char) GetDefinitions()[option_idx].short_option;
904    switch (short_option)
905    {
906        case 'r':
907            m_rsync = true;
908            break;
909
910        case 'R':
911            m_rsync_opts.assign(option_arg);
912            break;
913
914        case 'P':
915            m_rsync_prefix.assign(option_arg);
916            break;
917
918        case 'i':
919            m_ignores_remote_hostname = true;
920            break;
921
922        default:
923            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
924            break;
925    }
926
927    return error;
928}
929
930uint32_t
931OptionGroupPlatformRSync::GetNumDefinitions ()
932{
933    return llvm::array_lengthof(g_rsync_option_table);
934}
935
936lldb::BreakpointSP
937Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
938{
939    return lldb::BreakpointSP();
940}
941
942OptionGroupPlatformSSH::OptionGroupPlatformSSH ()
943{
944}
945
946OptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
947{
948}
949
950const lldb_private::OptionDefinition*
951OptionGroupPlatformSSH::GetDefinitions ()
952{
953    return g_ssh_option_table;
954}
955
956void
957OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
958{
959    m_ssh = false;
960    m_ssh_opts.clear();
961}
962
963lldb_private::Error
964OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
965                                          uint32_t option_idx,
966                                          const char *option_arg)
967{
968    Error error;
969    char short_option = (char) GetDefinitions()[option_idx].short_option;
970    switch (short_option)
971    {
972        case 's':
973            m_ssh = true;
974            break;
975
976        case 'S':
977            m_ssh_opts.assign(option_arg);
978            break;
979
980        default:
981            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
982            break;
983    }
984
985    return error;
986}
987
988uint32_t
989OptionGroupPlatformSSH::GetNumDefinitions ()
990{
991    return llvm::array_lengthof(g_ssh_option_table);
992}
993
994OptionGroupPlatformCaching::OptionGroupPlatformCaching ()
995{
996}
997
998OptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
999{
1000}
1001
1002const lldb_private::OptionDefinition*
1003OptionGroupPlatformCaching::GetDefinitions ()
1004{
1005    return g_caching_option_table;
1006}
1007
1008void
1009OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
1010{
1011    m_cache_dir.clear();
1012}
1013
1014lldb_private::Error
1015OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
1016                                        uint32_t option_idx,
1017                                        const char *option_arg)
1018{
1019    Error error;
1020    char short_option = (char) GetDefinitions()[option_idx].short_option;
1021    switch (short_option)
1022    {
1023        case 'c':
1024            m_cache_dir.assign(option_arg);
1025            break;
1026
1027        default:
1028            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1029            break;
1030    }
1031
1032    return error;
1033}
1034
1035uint32_t
1036OptionGroupPlatformCaching::GetNumDefinitions ()
1037{
1038    return llvm::array_lengthof(g_caching_option_table);
1039}
1040
1041size_t
1042Platform::GetEnvironment (StringList &environment)
1043{
1044    environment.Clear();
1045    return false;
1046}
1047