1254721Semaste//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Target/Platform.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h"
17254721Semaste#include "lldb/Core/Error.h"
18254721Semaste#include "lldb/Core/Log.h"
19254721Semaste#include "lldb/Core/ModuleSpec.h"
20254721Semaste#include "lldb/Core/PluginManager.h"
21254721Semaste#include "lldb/Host/FileSpec.h"
22254721Semaste#include "lldb/Host/Host.h"
23254721Semaste#include "lldb/Target/Process.h"
24254721Semaste#include "lldb/Target/Target.h"
25263363Semaste#include "lldb/Utility/Utils.h"
26254721Semaste
27254721Semasteusing namespace lldb;
28254721Semasteusing namespace lldb_private;
29254721Semaste
30254721Semaste// Use a singleton function for g_local_platform_sp to avoid init
31254721Semaste// constructors since LLDB is often part of a shared library
32254721Semastestatic PlatformSP&
33254721SemasteGetDefaultPlatformSP ()
34254721Semaste{
35254721Semaste    static PlatformSP g_default_platform_sp;
36254721Semaste    return g_default_platform_sp;
37254721Semaste}
38254721Semaste
39254721Semastestatic Mutex &
40254721SemasteGetConnectedPlatformListMutex ()
41254721Semaste{
42254721Semaste    static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
43254721Semaste    return g_remote_connected_platforms_mutex;
44254721Semaste}
45254721Semastestatic std::vector<PlatformSP> &
46254721SemasteGetConnectedPlatformList ()
47254721Semaste{
48254721Semaste    static std::vector<PlatformSP> g_remote_connected_platforms;
49254721Semaste    return g_remote_connected_platforms;
50254721Semaste}
51254721Semaste
52254721Semaste
53254721Semasteconst char *
54254721SemastePlatform::GetHostPlatformName ()
55254721Semaste{
56254721Semaste    return "host";
57254721Semaste}
58254721Semaste
59254721Semaste//------------------------------------------------------------------
60254721Semaste/// Get the native host platform plug-in.
61254721Semaste///
62254721Semaste/// There should only be one of these for each host that LLDB runs
63254721Semaste/// upon that should be statically compiled in and registered using
64254721Semaste/// preprocessor macros or other similar build mechanisms.
65254721Semaste///
66254721Semaste/// This platform will be used as the default platform when launching
67254721Semaste/// or attaching to processes unless another platform is specified.
68254721Semaste//------------------------------------------------------------------
69254721SemastePlatformSP
70254721SemastePlatform::GetDefaultPlatform ()
71254721Semaste{
72254721Semaste    return GetDefaultPlatformSP ();
73254721Semaste}
74254721Semaste
75254721Semastevoid
76254721SemastePlatform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
77254721Semaste{
78254721Semaste    // The native platform should use its static void Platform::Initialize()
79254721Semaste    // function to register itself as the native platform.
80254721Semaste    GetDefaultPlatformSP () = platform_sp;
81254721Semaste}
82254721Semaste
83254721SemasteError
84269024SemastePlatform::GetFileWithUUID (const FileSpec &platform_file,
85269024Semaste                           const UUID *uuid_ptr,
86269024Semaste                           FileSpec &local_file)
87254721Semaste{
88254721Semaste    // Default to the local case
89254721Semaste    local_file = platform_file;
90254721Semaste    return Error();
91254721Semaste}
92254721Semaste
93254721SemasteFileSpecList
94254721SemastePlatform::LocateExecutableScriptingResources (Target *target, Module &module)
95254721Semaste{
96254721Semaste    return FileSpecList();
97254721Semaste}
98254721Semaste
99254721SemastePlatform*
100254721SemastePlatform::FindPlugin (Process *process, const ConstString &plugin_name)
101254721Semaste{
102254721Semaste    PlatformCreateInstance create_callback = NULL;
103254721Semaste    if (plugin_name)
104254721Semaste    {
105254721Semaste        create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
106254721Semaste        if (create_callback)
107254721Semaste        {
108254721Semaste            ArchSpec arch;
109254721Semaste            if (process)
110254721Semaste            {
111254721Semaste                arch = process->GetTarget().GetArchitecture();
112254721Semaste            }
113254721Semaste            std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
114254721Semaste            if (instance_ap.get())
115254721Semaste                return instance_ap.release();
116254721Semaste        }
117254721Semaste    }
118254721Semaste    else
119254721Semaste    {
120254721Semaste        for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
121254721Semaste        {
122254721Semaste            std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
123254721Semaste            if (instance_ap.get())
124254721Semaste                return instance_ap.release();
125254721Semaste        }
126254721Semaste    }
127254721Semaste    return NULL;
128254721Semaste}
129254721Semaste
130254721SemasteError
131254721SemastePlatform::GetSharedModule (const ModuleSpec &module_spec,
132254721Semaste                           ModuleSP &module_sp,
133254721Semaste                           const FileSpecList *module_search_paths_ptr,
134254721Semaste                           ModuleSP *old_module_sp_ptr,
135254721Semaste                           bool *did_create_ptr)
136254721Semaste{
137254721Semaste    // Don't do any path remapping for the default implementation
138254721Semaste    // of the platform GetSharedModule function, just call through
139254721Semaste    // to our static ModuleList function. Platform subclasses that
140254721Semaste    // implement remote debugging, might have a developer kits
141254721Semaste    // installed that have cached versions of the files for the
142254721Semaste    // remote target, or might implement a download and cache
143254721Semaste    // locally implementation.
144254721Semaste    const bool always_create = false;
145254721Semaste    return ModuleList::GetSharedModule (module_spec,
146254721Semaste                                        module_sp,
147254721Semaste                                        module_search_paths_ptr,
148254721Semaste                                        old_module_sp_ptr,
149254721Semaste                                        did_create_ptr,
150254721Semaste                                        always_create);
151254721Semaste}
152254721Semaste
153254721SemastePlatformSP
154254721SemastePlatform::Create (const char *platform_name, Error &error)
155254721Semaste{
156254721Semaste    PlatformCreateInstance create_callback = NULL;
157254721Semaste    lldb::PlatformSP platform_sp;
158254721Semaste    if (platform_name && platform_name[0])
159254721Semaste    {
160254721Semaste        ConstString const_platform_name (platform_name);
161254721Semaste        create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
162254721Semaste        if (create_callback)
163254721Semaste            platform_sp.reset(create_callback(true, NULL));
164254721Semaste        else
165254721Semaste            error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
166254721Semaste    }
167254721Semaste    else
168254721Semaste        error.SetErrorString ("invalid platform name");
169254721Semaste    return platform_sp;
170254721Semaste}
171254721Semaste
172254721Semaste
173254721SemastePlatformSP
174254721SemastePlatform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
175254721Semaste{
176254721Semaste    lldb::PlatformSP platform_sp;
177254721Semaste    if (arch.IsValid())
178254721Semaste    {
179254721Semaste        uint32_t idx;
180254721Semaste        PlatformCreateInstance create_callback;
181254721Semaste        // First try exact arch matches across all platform plug-ins
182254721Semaste        bool exact = true;
183254721Semaste        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
184254721Semaste        {
185254721Semaste            if (create_callback)
186254721Semaste            {
187254721Semaste                platform_sp.reset(create_callback(false, &arch));
188254721Semaste                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
189254721Semaste                    return platform_sp;
190254721Semaste            }
191254721Semaste        }
192254721Semaste        // Next try compatible arch matches across all platform plug-ins
193254721Semaste        exact = false;
194254721Semaste        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
195254721Semaste        {
196254721Semaste            if (create_callback)
197254721Semaste            {
198254721Semaste                platform_sp.reset(create_callback(false, &arch));
199254721Semaste                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
200254721Semaste                    return platform_sp;
201254721Semaste            }
202254721Semaste        }
203254721Semaste    }
204254721Semaste    else
205254721Semaste        error.SetErrorString ("invalid platform name");
206254721Semaste    if (platform_arch_ptr)
207254721Semaste        platform_arch_ptr->Clear();
208254721Semaste    platform_sp.reset();
209254721Semaste    return platform_sp;
210254721Semaste}
211254721Semaste
212254721Semasteuint32_t
213254721SemastePlatform::GetNumConnectedRemotePlatforms ()
214254721Semaste{
215254721Semaste    Mutex::Locker locker (GetConnectedPlatformListMutex ());
216254721Semaste    return GetConnectedPlatformList().size();
217254721Semaste}
218254721Semaste
219254721SemastePlatformSP
220254721SemastePlatform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
221254721Semaste{
222254721Semaste    PlatformSP platform_sp;
223254721Semaste    {
224254721Semaste        Mutex::Locker locker (GetConnectedPlatformListMutex ());
225254721Semaste        if (idx < GetConnectedPlatformList().size())
226254721Semaste            platform_sp = GetConnectedPlatformList ()[idx];
227254721Semaste    }
228254721Semaste    return platform_sp;
229254721Semaste}
230254721Semaste
231254721Semaste//------------------------------------------------------------------
232254721Semaste/// Default Constructor
233254721Semaste//------------------------------------------------------------------
234254721SemastePlatform::Platform (bool is_host) :
235254721Semaste    m_is_host (is_host),
236254721Semaste    m_os_version_set_while_connected (false),
237254721Semaste    m_system_arch_set_while_connected (false),
238254721Semaste    m_sdk_sysroot (),
239254721Semaste    m_sdk_build (),
240263367Semaste    m_working_dir (),
241254721Semaste    m_remote_url (),
242254721Semaste    m_name (),
243254721Semaste    m_major_os_version (UINT32_MAX),
244254721Semaste    m_minor_os_version (UINT32_MAX),
245254721Semaste    m_update_os_version (UINT32_MAX),
246254721Semaste    m_system_arch(),
247254721Semaste    m_uid_map_mutex (Mutex::eMutexTypeNormal),
248254721Semaste    m_gid_map_mutex (Mutex::eMutexTypeNormal),
249254721Semaste    m_uid_map(),
250254721Semaste    m_gid_map(),
251254721Semaste    m_max_uid_name_len (0),
252263363Semaste    m_max_gid_name_len (0),
253263363Semaste    m_supports_rsync (false),
254263363Semaste    m_rsync_opts (),
255263363Semaste    m_rsync_prefix (),
256263363Semaste    m_supports_ssh (false),
257263363Semaste    m_ssh_opts (),
258269024Semaste    m_ignores_remote_hostname (false),
259269024Semaste    m_trap_handlers(),
260269024Semaste    m_calculated_trap_handlers (false)
261254721Semaste{
262254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
263254721Semaste    if (log)
264254721Semaste        log->Printf ("%p Platform::Platform()", this);
265254721Semaste}
266254721Semaste
267254721Semaste//------------------------------------------------------------------
268254721Semaste/// Destructor.
269254721Semaste///
270254721Semaste/// The destructor is virtual since this class is designed to be
271254721Semaste/// inherited from by the plug-in instance.
272254721Semaste//------------------------------------------------------------------
273254721SemastePlatform::~Platform()
274254721Semaste{
275254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
276254721Semaste    if (log)
277254721Semaste        log->Printf ("%p Platform::~Platform()", this);
278254721Semaste}
279254721Semaste
280254721Semastevoid
281254721SemastePlatform::GetStatus (Stream &strm)
282254721Semaste{
283254721Semaste    uint32_t major = UINT32_MAX;
284254721Semaste    uint32_t minor = UINT32_MAX;
285254721Semaste    uint32_t update = UINT32_MAX;
286254721Semaste    std::string s;
287254721Semaste    strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
288254721Semaste
289254721Semaste    ArchSpec arch (GetSystemArchitecture());
290254721Semaste    if (arch.IsValid())
291254721Semaste    {
292254721Semaste        if (!arch.GetTriple().str().empty())
293254721Semaste        strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
294254721Semaste    }
295254721Semaste
296254721Semaste    if (GetOSVersion(major, minor, update))
297254721Semaste    {
298254721Semaste        strm.Printf("OS Version: %u", major);
299254721Semaste        if (minor != UINT32_MAX)
300254721Semaste            strm.Printf(".%u", minor);
301254721Semaste        if (update != UINT32_MAX)
302254721Semaste            strm.Printf(".%u", update);
303254721Semaste
304254721Semaste        if (GetOSBuildString (s))
305254721Semaste            strm.Printf(" (%s)", s.c_str());
306254721Semaste
307254721Semaste        strm.EOL();
308254721Semaste    }
309254721Semaste
310254721Semaste    if (GetOSKernelDescription (s))
311254721Semaste        strm.Printf("    Kernel: %s\n", s.c_str());
312254721Semaste
313254721Semaste    if (IsHost())
314254721Semaste    {
315254721Semaste        strm.Printf("  Hostname: %s\n", GetHostname());
316254721Semaste    }
317254721Semaste    else
318254721Semaste    {
319254721Semaste        const bool is_connected = IsConnected();
320254721Semaste        if (is_connected)
321254721Semaste            strm.Printf("  Hostname: %s\n", GetHostname());
322254721Semaste        strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
323254721Semaste    }
324263363Semaste
325263367Semaste    if (GetWorkingDirectory())
326263367Semaste    {
327263367Semaste        strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString());
328263367Semaste    }
329263363Semaste    if (!IsConnected())
330263363Semaste        return;
331263363Semaste
332263363Semaste    std::string specific_info(GetPlatformSpecificConnectionInformation());
333263363Semaste
334263363Semaste    if (specific_info.empty() == false)
335263363Semaste        strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());
336254721Semaste}
337254721Semaste
338254721Semaste
339254721Semastebool
340254721SemastePlatform::GetOSVersion (uint32_t &major,
341254721Semaste                        uint32_t &minor,
342254721Semaste                        uint32_t &update)
343254721Semaste{
344254721Semaste    bool success = m_major_os_version != UINT32_MAX;
345254721Semaste    if (IsHost())
346254721Semaste    {
347254721Semaste        if (!success)
348254721Semaste        {
349254721Semaste            // We have a local host platform
350254721Semaste            success = Host::GetOSVersion (m_major_os_version,
351254721Semaste                                          m_minor_os_version,
352254721Semaste                                          m_update_os_version);
353254721Semaste            m_os_version_set_while_connected = success;
354254721Semaste        }
355254721Semaste    }
356254721Semaste    else
357254721Semaste    {
358254721Semaste        // We have a remote platform. We can only fetch the remote
359254721Semaste        // OS version if we are connected, and we don't want to do it
360254721Semaste        // more than once.
361254721Semaste
362254721Semaste        const bool is_connected = IsConnected();
363254721Semaste
364254721Semaste        bool fetch = false;
365254721Semaste        if (success)
366254721Semaste        {
367254721Semaste            // We have valid OS version info, check to make sure it wasn't
368254721Semaste            // manually set prior to connecting. If it was manually set prior
369254721Semaste            // to connecting, then lets fetch the actual OS version info
370254721Semaste            // if we are now connected.
371254721Semaste            if (is_connected && !m_os_version_set_while_connected)
372254721Semaste                fetch = true;
373254721Semaste        }
374254721Semaste        else
375254721Semaste        {
376254721Semaste            // We don't have valid OS version info, fetch it if we are connected
377254721Semaste            fetch = is_connected;
378254721Semaste        }
379254721Semaste
380254721Semaste        if (fetch)
381254721Semaste        {
382254721Semaste            success = GetRemoteOSVersion ();
383254721Semaste            m_os_version_set_while_connected = success;
384254721Semaste        }
385254721Semaste    }
386254721Semaste
387254721Semaste    if (success)
388254721Semaste    {
389254721Semaste        major = m_major_os_version;
390254721Semaste        minor = m_minor_os_version;
391254721Semaste        update = m_update_os_version;
392254721Semaste    }
393254721Semaste    return success;
394254721Semaste}
395254721Semaste
396254721Semastebool
397254721SemastePlatform::GetOSBuildString (std::string &s)
398254721Semaste{
399254721Semaste    if (IsHost())
400254721Semaste        return Host::GetOSBuildString (s);
401254721Semaste    else
402254721Semaste        return GetRemoteOSBuildString (s);
403254721Semaste}
404254721Semaste
405254721Semastebool
406254721SemastePlatform::GetOSKernelDescription (std::string &s)
407254721Semaste{
408254721Semaste    if (IsHost())
409254721Semaste        return Host::GetOSKernelDescription (s);
410254721Semaste    else
411254721Semaste        return GetRemoteOSKernelDescription (s);
412254721Semaste}
413254721Semaste
414254721SemasteConstString
415263367SemastePlatform::GetWorkingDirectory ()
416263367Semaste{
417263367Semaste    if (IsHost())
418263367Semaste    {
419263367Semaste        char cwd[PATH_MAX];
420263367Semaste        if (getcwd(cwd, sizeof(cwd)))
421263367Semaste            return ConstString(cwd);
422263367Semaste        else
423263367Semaste            return ConstString();
424263367Semaste    }
425263367Semaste    else
426263367Semaste    {
427263367Semaste        if (!m_working_dir)
428263367Semaste            m_working_dir = GetRemoteWorkingDirectory();
429263367Semaste        return m_working_dir;
430263367Semaste    }
431263367Semaste}
432263367Semaste
433263367Semaste
434263367Semastestruct RecurseCopyBaton
435263367Semaste{
436263367Semaste    const FileSpec& dst;
437263367Semaste    Platform *platform_ptr;
438263367Semaste    Error error;
439263367Semaste};
440263367Semaste
441263367Semaste
442263367Semastestatic FileSpec::EnumerateDirectoryResult
443263367SemasteRecurseCopy_Callback (void *baton,
444263367Semaste                      FileSpec::FileType file_type,
445263367Semaste                      const FileSpec &src)
446263367Semaste{
447263367Semaste    RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
448263367Semaste    switch (file_type)
449263367Semaste    {
450263367Semaste        case FileSpec::eFileTypePipe:
451263367Semaste        case FileSpec::eFileTypeSocket:
452263367Semaste            // we have no way to copy pipes and sockets - ignore them and continue
453263367Semaste            return FileSpec::eEnumerateDirectoryResultNext;
454263367Semaste            break;
455263367Semaste
456263367Semaste        case FileSpec::eFileTypeDirectory:
457263367Semaste            {
458263367Semaste                // make the new directory and get in there
459263367Semaste                FileSpec dst_dir = rc_baton->dst;
460263367Semaste                if (!dst_dir.GetFilename())
461263367Semaste                    dst_dir.GetFilename() = src.GetLastPathComponent();
462263367Semaste                std::string dst_dir_path (dst_dir.GetPath());
463263367Semaste                Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
464263367Semaste                if (error.Fail())
465263367Semaste                {
466263367Semaste                    rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
467263367Semaste                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
468263367Semaste                }
469263367Semaste
470263367Semaste                // now recurse
471263367Semaste                std::string src_dir_path (src.GetPath());
472263367Semaste
473263367Semaste                // Make a filespec that only fills in the directory of a FileSpec so
474263367Semaste                // when we enumerate we can quickly fill in the filename for dst copies
475263367Semaste                FileSpec recurse_dst;
476263367Semaste                recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
477263367Semaste                RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() };
478263367Semaste                FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
479263367Semaste                if (rc_baton2.error.Fail())
480263367Semaste                {
481263367Semaste                    rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
482263367Semaste                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
483263367Semaste                }
484263367Semaste                return FileSpec::eEnumerateDirectoryResultNext;
485263367Semaste            }
486263367Semaste            break;
487263367Semaste
488263367Semaste        case FileSpec::eFileTypeSymbolicLink:
489263367Semaste            {
490263367Semaste                // copy the file and keep going
491263367Semaste                FileSpec dst_file = rc_baton->dst;
492263367Semaste                if (!dst_file.GetFilename())
493263367Semaste                    dst_file.GetFilename() = src.GetFilename();
494263367Semaste
495263367Semaste                char buf[PATH_MAX];
496263367Semaste
497263367Semaste                rc_baton->error = Host::Readlink (src.GetPath().c_str(), buf, sizeof(buf));
498263367Semaste
499263367Semaste                if (rc_baton->error.Fail())
500263367Semaste                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
501263367Semaste
502263367Semaste                rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);
503263367Semaste
504263367Semaste                if (rc_baton->error.Fail())
505263367Semaste                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
506263367Semaste
507263367Semaste                return FileSpec::eEnumerateDirectoryResultNext;
508263367Semaste            }
509263367Semaste            break;
510263367Semaste        case FileSpec::eFileTypeRegular:
511263367Semaste            {
512263367Semaste                // copy the file and keep going
513263367Semaste                FileSpec dst_file = rc_baton->dst;
514263367Semaste                if (!dst_file.GetFilename())
515263367Semaste                    dst_file.GetFilename() = src.GetFilename();
516263367Semaste                Error err = rc_baton->platform_ptr->PutFile(src, dst_file);
517263367Semaste                if (err.Fail())
518263367Semaste                {
519263367Semaste                    rc_baton->error.SetErrorString(err.AsCString());
520263367Semaste                    return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
521263367Semaste                }
522263367Semaste                return FileSpec::eEnumerateDirectoryResultNext;
523263367Semaste            }
524263367Semaste            break;
525263367Semaste
526263367Semaste        case FileSpec::eFileTypeInvalid:
527263367Semaste        case FileSpec::eFileTypeOther:
528263367Semaste        case FileSpec::eFileTypeUnknown:
529263367Semaste            rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
530263367Semaste            return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
531263367Semaste            break;
532263367Semaste    }
533263367Semaste}
534263367Semaste
535263367SemasteError
536263367SemastePlatform::Install (const FileSpec& src, const FileSpec& dst)
537263367Semaste{
538263367Semaste    Error error;
539263367Semaste
540263367Semaste    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
541263367Semaste    if (log)
542263367Semaste        log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str());
543263367Semaste    FileSpec fixed_dst(dst);
544263367Semaste
545263367Semaste    if (!fixed_dst.GetFilename())
546263367Semaste        fixed_dst.GetFilename() = src.GetFilename();
547263367Semaste
548263367Semaste    ConstString working_dir = GetWorkingDirectory();
549263367Semaste
550263367Semaste    if (dst)
551263367Semaste    {
552263367Semaste        if (dst.GetDirectory())
553263367Semaste        {
554263367Semaste            const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
555263367Semaste            if (first_dst_dir_char == '/' || first_dst_dir_char  == '\\')
556263367Semaste            {
557263367Semaste                fixed_dst.GetDirectory() = dst.GetDirectory();
558263367Semaste            }
559263367Semaste            // If the fixed destination file doesn't have a directory yet,
560263367Semaste            // then we must have a relative path. We will resolve this relative
561263367Semaste            // path against the platform's working directory
562263367Semaste            if (!fixed_dst.GetDirectory())
563263367Semaste            {
564263367Semaste                FileSpec relative_spec;
565263367Semaste                std::string path;
566263367Semaste                if (working_dir)
567263367Semaste                {
568263367Semaste                    relative_spec.SetFile(working_dir.GetCString(), false);
569263367Semaste                    relative_spec.AppendPathComponent(dst.GetPath().c_str());
570263367Semaste                    fixed_dst.GetDirectory() = relative_spec.GetDirectory();
571263367Semaste                }
572263367Semaste                else
573263367Semaste                {
574263367Semaste                    error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
575263367Semaste                    return error;
576263367Semaste                }
577263367Semaste            }
578263367Semaste        }
579263367Semaste        else
580263367Semaste        {
581263367Semaste            if (working_dir)
582263367Semaste            {
583263367Semaste                fixed_dst.GetDirectory() = working_dir;
584263367Semaste            }
585263367Semaste            else
586263367Semaste            {
587263367Semaste                error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
588263367Semaste                return error;
589263367Semaste            }
590263367Semaste        }
591263367Semaste    }
592263367Semaste    else
593263367Semaste    {
594263367Semaste        if (working_dir)
595263367Semaste        {
596263367Semaste            fixed_dst.GetDirectory() = working_dir;
597263367Semaste        }
598263367Semaste        else
599263367Semaste        {
600263367Semaste            error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty");
601263367Semaste            return error;
602263367Semaste        }
603263367Semaste    }
604263367Semaste
605263367Semaste    if (log)
606263367Semaste        log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str());
607263367Semaste
608263367Semaste    if (GetSupportsRSync())
609263367Semaste    {
610263367Semaste        error = PutFile(src, dst);
611263367Semaste    }
612263367Semaste    else
613263367Semaste    {
614263367Semaste        switch (src.GetFileType())
615263367Semaste        {
616263367Semaste            case FileSpec::eFileTypeDirectory:
617263367Semaste                {
618263367Semaste                    if (GetFileExists (fixed_dst))
619263367Semaste                        Unlink (fixed_dst.GetPath().c_str());
620263367Semaste                    uint32_t permissions = src.GetPermissions();
621263367Semaste                    if (permissions == 0)
622263367Semaste                        permissions = eFilePermissionsDirectoryDefault;
623263367Semaste                    std::string dst_dir_path(fixed_dst.GetPath());
624263367Semaste                    error = MakeDirectory(dst_dir_path.c_str(), permissions);
625263367Semaste                    if (error.Success())
626263367Semaste                    {
627263367Semaste                        // Make a filespec that only fills in the directory of a FileSpec so
628263367Semaste                        // when we enumerate we can quickly fill in the filename for dst copies
629263367Semaste                        FileSpec recurse_dst;
630263367Semaste                        recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
631263367Semaste                        std::string src_dir_path (src.GetPath());
632263367Semaste                        RecurseCopyBaton baton = { recurse_dst, this, Error() };
633263367Semaste                        FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
634263367Semaste                        return baton.error;
635263367Semaste                    }
636263367Semaste                }
637263367Semaste                break;
638263367Semaste
639263367Semaste            case FileSpec::eFileTypeRegular:
640263367Semaste                if (GetFileExists (fixed_dst))
641263367Semaste                    Unlink (fixed_dst.GetPath().c_str());
642263367Semaste                error = PutFile(src, fixed_dst);
643263367Semaste                break;
644263367Semaste
645263367Semaste            case FileSpec::eFileTypeSymbolicLink:
646263367Semaste                {
647263367Semaste                    if (GetFileExists (fixed_dst))
648263367Semaste                        Unlink (fixed_dst.GetPath().c_str());
649263367Semaste                    char buf[PATH_MAX];
650263367Semaste                    error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
651263367Semaste                    if (error.Success())
652263367Semaste                        error = CreateSymlink(dst.GetPath().c_str(), buf);
653263367Semaste                }
654263367Semaste                break;
655263367Semaste            case FileSpec::eFileTypePipe:
656263367Semaste                error.SetErrorString("platform install doesn't handle pipes");
657263367Semaste                break;
658263367Semaste            case FileSpec::eFileTypeSocket:
659263367Semaste                error.SetErrorString("platform install doesn't handle sockets");
660263367Semaste                break;
661263367Semaste            case FileSpec::eFileTypeInvalid:
662263367Semaste            case FileSpec::eFileTypeUnknown:
663263367Semaste            case FileSpec::eFileTypeOther:
664263367Semaste                error.SetErrorString("platform install doesn't handle non file or directory items");
665263367Semaste                break;
666263367Semaste        }
667263367Semaste    }
668263367Semaste    return error;
669263367Semaste}
670263367Semaste
671263367Semastebool
672263367SemastePlatform::SetWorkingDirectory (const ConstString &path)
673263367Semaste{
674263367Semaste    if (IsHost())
675263367Semaste    {
676263367Semaste        Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
677263367Semaste        if (log)
678263367Semaste            log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString());
679263367Semaste#ifdef _WIN32
680263367Semaste        // Not implemented on Windows
681263367Semaste        return false;
682263367Semaste#else
683263367Semaste        if (path)
684263367Semaste        {
685263367Semaste            if (chdir(path.GetCString()) == 0)
686263367Semaste                return true;
687263367Semaste        }
688263367Semaste        return false;
689263367Semaste#endif
690263367Semaste    }
691263367Semaste    else
692263367Semaste    {
693263367Semaste        m_working_dir.Clear();
694263367Semaste        return SetRemoteWorkingDirectory(path);
695263367Semaste    }
696263367Semaste}
697263367Semaste
698263367SemasteError
699263367SemastePlatform::MakeDirectory (const char *path, uint32_t permissions)
700263367Semaste{
701263367Semaste    if (IsHost())
702263367Semaste        return Host::MakeDirectory (path, permissions);
703263367Semaste    else
704263367Semaste    {
705263367Semaste        Error error;
706263367Semaste        error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
707263367Semaste        return error;
708263367Semaste    }
709263367Semaste}
710263367Semaste
711263367SemasteError
712263367SemastePlatform::GetFilePermissions (const char *path, uint32_t &file_permissions)
713263367Semaste{
714263367Semaste    if (IsHost())
715263367Semaste        return Host::GetFilePermissions(path, file_permissions);
716263367Semaste    else
717263367Semaste    {
718263367Semaste        Error error;
719263367Semaste        error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
720263367Semaste        return error;
721263367Semaste    }
722263367Semaste}
723263367Semaste
724263367SemasteError
725263367SemastePlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
726263367Semaste{
727263367Semaste    if (IsHost())
728263367Semaste        return Host::SetFilePermissions(path, file_permissions);
729263367Semaste    else
730263367Semaste    {
731263367Semaste        Error error;
732263367Semaste        error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
733263367Semaste        return error;
734263367Semaste    }
735263367Semaste}
736263367Semaste
737263367SemasteConstString
738254721SemastePlatform::GetName ()
739254721Semaste{
740263367Semaste    return GetPluginName();
741254721Semaste}
742254721Semaste
743254721Semasteconst char *
744254721SemastePlatform::GetHostname ()
745254721Semaste{
746254721Semaste    if (IsHost())
747254721Semaste        return "localhost";
748254721Semaste
749254721Semaste    if (m_name.empty())
750254721Semaste        return NULL;
751254721Semaste    return m_name.c_str();
752254721Semaste}
753254721Semaste
754263367Semastebool
755263367SemastePlatform::SetRemoteWorkingDirectory(const ConstString &path)
756263367Semaste{
757263367Semaste    Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
758263367Semaste    if (log)
759263367Semaste        log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString());
760263367Semaste    m_working_dir = path;
761263367Semaste    return true;
762263367Semaste}
763263367Semaste
764254721Semasteconst char *
765254721SemastePlatform::GetUserName (uint32_t uid)
766254721Semaste{
767254721Semaste    const char *user_name = GetCachedUserName(uid);
768254721Semaste    if (user_name)
769254721Semaste        return user_name;
770254721Semaste    if (IsHost())
771254721Semaste    {
772254721Semaste        std::string name;
773254721Semaste        if (Host::GetUserName(uid, name))
774254721Semaste            return SetCachedUserName (uid, name.c_str(), name.size());
775254721Semaste    }
776254721Semaste    return NULL;
777254721Semaste}
778254721Semaste
779254721Semasteconst char *
780254721SemastePlatform::GetGroupName (uint32_t gid)
781254721Semaste{
782254721Semaste    const char *group_name = GetCachedGroupName(gid);
783254721Semaste    if (group_name)
784254721Semaste        return group_name;
785254721Semaste    if (IsHost())
786254721Semaste    {
787254721Semaste        std::string name;
788254721Semaste        if (Host::GetGroupName(gid, name))
789254721Semaste            return SetCachedGroupName (gid, name.c_str(), name.size());
790254721Semaste    }
791254721Semaste    return NULL;
792254721Semaste}
793254721Semaste
794254721Semastebool
795254721SemastePlatform::SetOSVersion (uint32_t major,
796254721Semaste                        uint32_t minor,
797254721Semaste                        uint32_t update)
798254721Semaste{
799254721Semaste    if (IsHost())
800254721Semaste    {
801254721Semaste        // We don't need anyone setting the OS version for the host platform,
802254721Semaste        // we should be able to figure it out by calling Host::GetOSVersion(...).
803254721Semaste        return false;
804254721Semaste    }
805254721Semaste    else
806254721Semaste    {
807254721Semaste        // We have a remote platform, allow setting the target OS version if
808254721Semaste        // we aren't connected, since if we are connected, we should be able to
809254721Semaste        // request the remote OS version from the connected platform.
810254721Semaste        if (IsConnected())
811254721Semaste            return false;
812254721Semaste        else
813254721Semaste        {
814254721Semaste            // We aren't connected and we might want to set the OS version
815254721Semaste            // ahead of time before we connect so we can peruse files and
816254721Semaste            // use a local SDK or PDK cache of support files to disassemble
817254721Semaste            // or do other things.
818254721Semaste            m_major_os_version = major;
819254721Semaste            m_minor_os_version = minor;
820254721Semaste            m_update_os_version = update;
821254721Semaste            return true;
822254721Semaste        }
823254721Semaste    }
824254721Semaste    return false;
825254721Semaste}
826254721Semaste
827254721Semaste
828254721SemasteError
829254721SemastePlatform::ResolveExecutable (const FileSpec &exe_file,
830254721Semaste                             const ArchSpec &exe_arch,
831254721Semaste                             lldb::ModuleSP &exe_module_sp,
832254721Semaste                             const FileSpecList *module_search_paths_ptr)
833254721Semaste{
834254721Semaste    Error error;
835254721Semaste    if (exe_file.Exists())
836254721Semaste    {
837254721Semaste        ModuleSpec module_spec (exe_file, exe_arch);
838254721Semaste        if (module_spec.GetArchitecture().IsValid())
839254721Semaste        {
840254721Semaste            error = ModuleList::GetSharedModule (module_spec,
841254721Semaste                                                 exe_module_sp,
842254721Semaste                                                 module_search_paths_ptr,
843254721Semaste                                                 NULL,
844254721Semaste                                                 NULL);
845254721Semaste        }
846254721Semaste        else
847254721Semaste        {
848254721Semaste            // No valid architecture was specified, ask the platform for
849254721Semaste            // the architectures that we should be using (in the correct order)
850254721Semaste            // and see if we can find a match that way
851254721Semaste            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
852254721Semaste            {
853254721Semaste                error = ModuleList::GetSharedModule (module_spec,
854254721Semaste                                                     exe_module_sp,
855254721Semaste                                                     module_search_paths_ptr,
856254721Semaste                                                     NULL,
857254721Semaste                                                     NULL);
858254721Semaste                // Did we find an executable using one of the
859254721Semaste                if (error.Success() && exe_module_sp)
860254721Semaste                    break;
861254721Semaste            }
862254721Semaste        }
863254721Semaste    }
864254721Semaste    else
865254721Semaste    {
866254721Semaste        error.SetErrorStringWithFormat ("'%s' does not exist",
867254721Semaste                                        exe_file.GetPath().c_str());
868254721Semaste    }
869254721Semaste    return error;
870254721Semaste}
871254721Semaste
872254721SemasteError
873254721SemastePlatform::ResolveSymbolFile (Target &target,
874254721Semaste                             const ModuleSpec &sym_spec,
875254721Semaste                             FileSpec &sym_file)
876254721Semaste{
877254721Semaste    Error error;
878254721Semaste    if (sym_spec.GetSymbolFileSpec().Exists())
879254721Semaste        sym_file = sym_spec.GetSymbolFileSpec();
880254721Semaste    else
881254721Semaste        error.SetErrorString("unable to resolve symbol file");
882254721Semaste    return error;
883254721Semaste
884254721Semaste}
885254721Semaste
886254721Semaste
887254721Semaste
888254721Semastebool
889254721SemastePlatform::ResolveRemotePath (const FileSpec &platform_path,
890254721Semaste                             FileSpec &resolved_platform_path)
891254721Semaste{
892254721Semaste    resolved_platform_path = platform_path;
893254721Semaste    return resolved_platform_path.ResolvePath();
894254721Semaste}
895254721Semaste
896254721Semaste
897254721Semasteconst ArchSpec &
898254721SemastePlatform::GetSystemArchitecture()
899254721Semaste{
900254721Semaste    if (IsHost())
901254721Semaste    {
902254721Semaste        if (!m_system_arch.IsValid())
903254721Semaste        {
904254721Semaste            // We have a local host platform
905254721Semaste            m_system_arch = Host::GetArchitecture();
906254721Semaste            m_system_arch_set_while_connected = m_system_arch.IsValid();
907254721Semaste        }
908254721Semaste    }
909254721Semaste    else
910254721Semaste    {
911254721Semaste        // We have a remote platform. We can only fetch the remote
912254721Semaste        // system architecture if we are connected, and we don't want to do it
913254721Semaste        // more than once.
914254721Semaste
915254721Semaste        const bool is_connected = IsConnected();
916254721Semaste
917254721Semaste        bool fetch = false;
918254721Semaste        if (m_system_arch.IsValid())
919254721Semaste        {
920254721Semaste            // We have valid OS version info, check to make sure it wasn't
921254721Semaste            // manually set prior to connecting. If it was manually set prior
922254721Semaste            // to connecting, then lets fetch the actual OS version info
923254721Semaste            // if we are now connected.
924254721Semaste            if (is_connected && !m_system_arch_set_while_connected)
925254721Semaste                fetch = true;
926254721Semaste        }
927254721Semaste        else
928254721Semaste        {
929254721Semaste            // We don't have valid OS version info, fetch it if we are connected
930254721Semaste            fetch = is_connected;
931254721Semaste        }
932254721Semaste
933254721Semaste        if (fetch)
934254721Semaste        {
935254721Semaste            m_system_arch = GetRemoteSystemArchitecture ();
936254721Semaste            m_system_arch_set_while_connected = m_system_arch.IsValid();
937254721Semaste        }
938254721Semaste    }
939254721Semaste    return m_system_arch;
940254721Semaste}
941254721Semaste
942254721Semaste
943254721SemasteError
944254721SemastePlatform::ConnectRemote (Args& args)
945254721Semaste{
946254721Semaste    Error error;
947254721Semaste    if (IsHost())
948254721Semaste        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
949254721Semaste    else
950254721Semaste        error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
951254721Semaste    return error;
952254721Semaste}
953254721Semaste
954254721SemasteError
955254721SemastePlatform::DisconnectRemote ()
956254721Semaste{
957254721Semaste    Error error;
958254721Semaste    if (IsHost())
959254721Semaste        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
960254721Semaste    else
961254721Semaste        error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
962254721Semaste    return error;
963254721Semaste}
964254721Semaste
965254721Semastebool
966254721SemastePlatform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
967254721Semaste{
968254721Semaste    // Take care of the host case so that each subclass can just
969254721Semaste    // call this function to get the host functionality.
970254721Semaste    if (IsHost())
971254721Semaste        return Host::GetProcessInfo (pid, process_info);
972254721Semaste    return false;
973254721Semaste}
974254721Semaste
975254721Semasteuint32_t
976254721SemastePlatform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
977254721Semaste                         ProcessInstanceInfoList &process_infos)
978254721Semaste{
979254721Semaste    // Take care of the host case so that each subclass can just
980254721Semaste    // call this function to get the host functionality.
981254721Semaste    uint32_t match_count = 0;
982254721Semaste    if (IsHost())
983254721Semaste        match_count = Host::FindProcesses (match_info, process_infos);
984254721Semaste    return match_count;
985254721Semaste}
986254721Semaste
987254721Semaste
988254721SemasteError
989254721SemastePlatform::LaunchProcess (ProcessLaunchInfo &launch_info)
990254721Semaste{
991254721Semaste    Error error;
992254721Semaste    // Take care of the host case so that each subclass can just
993254721Semaste    // call this function to get the host functionality.
994254721Semaste    if (IsHost())
995254721Semaste    {
996254721Semaste        if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
997254721Semaste            launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
998254721Semaste
999254721Semaste        if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
1000254721Semaste        {
1001254721Semaste            const bool is_localhost = true;
1002254721Semaste            const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
1003254721Semaste            const bool first_arg_is_full_shell_command = false;
1004263363Semaste            uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info);
1005254721Semaste            if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
1006254721Semaste                                                                  is_localhost,
1007254721Semaste                                                                  will_debug,
1008263363Semaste                                                                  first_arg_is_full_shell_command,
1009263363Semaste                                                                  num_resumes))
1010254721Semaste                return error;
1011254721Semaste        }
1012254721Semaste
1013254721Semaste        error = Host::LaunchProcess (launch_info);
1014254721Semaste    }
1015254721Semaste    else
1016254721Semaste        error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
1017254721Semaste    return error;
1018254721Semaste}
1019254721Semaste
1020254721Semastelldb::ProcessSP
1021254721SemastePlatform::DebugProcess (ProcessLaunchInfo &launch_info,
1022254721Semaste                        Debugger &debugger,
1023254721Semaste                        Target *target,       // Can be NULL, if NULL create a new target, else use existing one
1024254721Semaste                        Listener &listener,
1025254721Semaste                        Error &error)
1026254721Semaste{
1027254721Semaste    ProcessSP process_sp;
1028254721Semaste    // Make sure we stop at the entry point
1029254721Semaste    launch_info.GetFlags ().Set (eLaunchFlagDebug);
1030254721Semaste    // We always launch the process we are going to debug in a separate process
1031254721Semaste    // group, since then we can handle ^C interrupts ourselves w/o having to worry
1032254721Semaste    // about the target getting them as well.
1033254721Semaste    launch_info.SetLaunchInSeparateProcessGroup(true);
1034254721Semaste
1035254721Semaste    error = LaunchProcess (launch_info);
1036254721Semaste    if (error.Success())
1037254721Semaste    {
1038254721Semaste        if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1039254721Semaste        {
1040254721Semaste            ProcessAttachInfo attach_info (launch_info);
1041254721Semaste            process_sp = Attach (attach_info, debugger, target, listener, error);
1042254721Semaste            if (process_sp)
1043254721Semaste            {
1044269024Semaste                launch_info.SetHijackListener(attach_info.GetHijackListener());
1045269024Semaste
1046254721Semaste                // Since we attached to the process, it will think it needs to detach
1047254721Semaste                // if the process object just goes away without an explicit call to
1048254721Semaste                // Process::Kill() or Process::Detach(), so let it know to kill the
1049254721Semaste                // process if this happens.
1050254721Semaste                process_sp->SetShouldDetach (false);
1051254721Semaste
1052254721Semaste                // If we didn't have any file actions, the pseudo terminal might
1053254721Semaste                // have been used where the slave side was given as the file to
1054254721Semaste                // open for stdin/out/err after we have already opened the master
1055254721Semaste                // so we can read/write stdin/out/err.
1056254721Semaste                int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
1057254721Semaste                if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
1058254721Semaste                {
1059254721Semaste                    process_sp->SetSTDIOFileDescriptor(pty_fd);
1060254721Semaste                }
1061254721Semaste            }
1062254721Semaste        }
1063254721Semaste    }
1064254721Semaste    return process_sp;
1065254721Semaste}
1066254721Semaste
1067254721Semaste
1068254721Semastelldb::PlatformSP
1069254721SemastePlatform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
1070254721Semaste{
1071254721Semaste    lldb::PlatformSP platform_sp;
1072254721Semaste    Error error;
1073254721Semaste    if (arch.IsValid())
1074254721Semaste        platform_sp = Platform::Create (arch, platform_arch_ptr, error);
1075254721Semaste    return platform_sp;
1076254721Semaste}
1077254721Semaste
1078254721Semaste
1079254721Semaste//------------------------------------------------------------------
1080254721Semaste/// Lets a platform answer if it is compatible with a given
1081254721Semaste/// architecture and the target triple contained within.
1082254721Semaste//------------------------------------------------------------------
1083254721Semastebool
1084254721SemastePlatform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
1085254721Semaste{
1086254721Semaste    // If the architecture is invalid, we must answer true...
1087254721Semaste    if (arch.IsValid())
1088254721Semaste    {
1089254721Semaste        ArchSpec platform_arch;
1090254721Semaste        // Try for an exact architecture match first.
1091254721Semaste        if (exact_arch_match)
1092254721Semaste        {
1093254721Semaste            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1094254721Semaste            {
1095254721Semaste                if (arch.IsExactMatch(platform_arch))
1096254721Semaste                {
1097254721Semaste                    if (compatible_arch_ptr)
1098254721Semaste                        *compatible_arch_ptr = platform_arch;
1099254721Semaste                    return true;
1100254721Semaste                }
1101254721Semaste            }
1102254721Semaste        }
1103254721Semaste        else
1104254721Semaste        {
1105254721Semaste            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
1106254721Semaste            {
1107254721Semaste                if (arch.IsCompatibleMatch(platform_arch))
1108254721Semaste                {
1109254721Semaste                    if (compatible_arch_ptr)
1110254721Semaste                        *compatible_arch_ptr = platform_arch;
1111254721Semaste                    return true;
1112254721Semaste                }
1113254721Semaste            }
1114254721Semaste        }
1115254721Semaste    }
1116254721Semaste    if (compatible_arch_ptr)
1117254721Semaste        compatible_arch_ptr->Clear();
1118254721Semaste    return false;
1119263363Semaste}
1120263363Semaste
1121263363SemasteError
1122263363SemastePlatform::PutFile (const FileSpec& source,
1123263363Semaste                   const FileSpec& destination,
1124263363Semaste                   uint32_t uid,
1125263363Semaste                   uint32_t gid)
1126263363Semaste{
1127263363Semaste    Error error("unimplemented");
1128263363Semaste    return error;
1129263363Semaste}
1130263363Semaste
1131263363SemasteError
1132263363SemastePlatform::GetFile (const FileSpec& source,
1133263363Semaste                   const FileSpec& destination)
1134263363Semaste{
1135263363Semaste    Error error("unimplemented");
1136263363Semaste    return error;
1137263363Semaste}
1138263363Semaste
1139263367SemasteError
1140263367SemastePlatform::CreateSymlink (const char *src, // The name of the link is in src
1141263367Semaste                         const char *dst)// The symlink points to dst
1142263367Semaste{
1143263367Semaste    Error error("unimplemented");
1144263367Semaste    return error;
1145263367Semaste}
1146263367Semaste
1147263363Semastebool
1148263363SemastePlatform::GetFileExists (const lldb_private::FileSpec& file_spec)
1149263363Semaste{
1150263363Semaste    return false;
1151263363Semaste}
1152263363Semaste
1153263367SemasteError
1154263367SemastePlatform::Unlink (const char *path)
1155263367Semaste{
1156263367Semaste    Error error("unimplemented");
1157263367Semaste    return error;
1158263367Semaste}
1159263367Semaste
1160263367Semaste
1161263367Semaste
1162263363Semastelldb_private::Error
1163263363SemastePlatform::RunShellCommand (const char *command,           // Shouldn't be NULL
1164263363Semaste                           const char *working_dir,       // Pass NULL to use the current working directory
1165263363Semaste                           int *status_ptr,               // Pass NULL if you don't want the process exit status
1166263363Semaste                           int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit
1167263363Semaste                           std::string *command_output,   // Pass NULL if you don't want the command output
1168263363Semaste                           uint32_t timeout_sec)          // Timeout in seconds to wait for shell program to finish
1169263363Semaste{
1170263363Semaste    if (IsHost())
1171263363Semaste        return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
1172263363Semaste    else
1173263363Semaste        return Error("unimplemented");
1174263363Semaste}
1175263363Semaste
1176263363Semaste
1177263363Semastebool
1178263363SemastePlatform::CalculateMD5 (const FileSpec& file_spec,
1179263363Semaste                        uint64_t &low,
1180263363Semaste                        uint64_t &high)
1181263363Semaste{
1182263363Semaste    if (IsHost())
1183263363Semaste        return Host::CalculateMD5(file_spec, low, high);
1184263363Semaste    else
1185263363Semaste        return false;
1186263363Semaste}
1187263363Semaste
1188263363Semastevoid
1189263363SemastePlatform::SetLocalCacheDirectory (const char* local)
1190263363Semaste{
1191263363Semaste    m_local_cache_directory.assign(local);
1192263363Semaste}
1193263363Semaste
1194263363Semasteconst char*
1195263363SemastePlatform::GetLocalCacheDirectory ()
1196263363Semaste{
1197263363Semaste    return m_local_cache_directory.c_str();
1198263363Semaste}
1199263363Semaste
1200263363Semastestatic OptionDefinition
1201263363Semasteg_rsync_option_table[] =
1202263363Semaste{
1203263363Semaste    {   LLDB_OPT_SET_ALL, false, "rsync"                  , 'r', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Enable rsync." },
1204263363Semaste    {   LLDB_OPT_SET_ALL, false, "rsync-opts"             , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for rsync to work." },
1205263363Semaste    {   LLDB_OPT_SET_ALL, false, "rsync-prefix"           , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific rsync prefix put before the remote path." },
1206263363Semaste    {   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." },
1207263363Semaste};
1208263363Semaste
1209263363Semastestatic OptionDefinition
1210263363Semasteg_ssh_option_table[] =
1211263363Semaste{
1212263363Semaste    {   LLDB_OPT_SET_ALL, false, "ssh"                    , 's', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Enable SSH." },
1213263363Semaste    {   LLDB_OPT_SET_ALL, false, "ssh-opts"               , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName  , "Platform-specific options required for SSH to work." },
1214263363Semaste};
1215263363Semaste
1216263363Semastestatic OptionDefinition
1217263363Semasteg_caching_option_table[] =
1218263363Semaste{
1219263363Semaste    {   LLDB_OPT_SET_ALL, false, "local-cache-dir"        , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath         , "Path in which to store local copies of files." },
1220263363Semaste};
1221263363Semaste
1222263363SemasteOptionGroupPlatformRSync::OptionGroupPlatformRSync ()
1223263363Semaste{
1224263363Semaste}
1225263363Semaste
1226263363SemasteOptionGroupPlatformRSync::~OptionGroupPlatformRSync ()
1227263363Semaste{
1228263363Semaste}
1229263363Semaste
1230263363Semasteconst lldb_private::OptionDefinition*
1231263363SemasteOptionGroupPlatformRSync::GetDefinitions ()
1232263363Semaste{
1233263363Semaste    return g_rsync_option_table;
1234263363Semaste}
1235263363Semaste
1236263363Semastevoid
1237263363SemasteOptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter)
1238263363Semaste{
1239263363Semaste    m_rsync = false;
1240263363Semaste    m_rsync_opts.clear();
1241263363Semaste    m_rsync_prefix.clear();
1242263363Semaste    m_ignores_remote_hostname = false;
1243263363Semaste}
1244263363Semaste
1245263363Semastelldb_private::Error
1246263363SemasteOptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter,
1247263363Semaste                uint32_t option_idx,
1248263363Semaste                const char *option_arg)
1249263363Semaste{
1250263363Semaste    Error error;
1251263363Semaste    char short_option = (char) GetDefinitions()[option_idx].short_option;
1252263363Semaste    switch (short_option)
1253263363Semaste    {
1254263363Semaste        case 'r':
1255263363Semaste            m_rsync = true;
1256263363Semaste            break;
1257263363Semaste
1258263363Semaste        case 'R':
1259263363Semaste            m_rsync_opts.assign(option_arg);
1260263363Semaste            break;
1261263363Semaste
1262263363Semaste        case 'P':
1263263363Semaste            m_rsync_prefix.assign(option_arg);
1264263363Semaste            break;
1265263363Semaste
1266263363Semaste        case 'i':
1267263363Semaste            m_ignores_remote_hostname = true;
1268263363Semaste            break;
1269263363Semaste
1270263363Semaste        default:
1271263363Semaste            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1272263363Semaste            break;
1273263363Semaste    }
1274254721Semaste
1275263363Semaste    return error;
1276254721Semaste}
1277254721Semaste
1278263363Semasteuint32_t
1279263363SemasteOptionGroupPlatformRSync::GetNumDefinitions ()
1280263363Semaste{
1281263363Semaste    return llvm::array_lengthof(g_rsync_option_table);
1282263363Semaste}
1283254721Semaste
1284254721Semastelldb::BreakpointSP
1285254721SemastePlatform::SetThreadCreationBreakpoint (lldb_private::Target &target)
1286254721Semaste{
1287254721Semaste    return lldb::BreakpointSP();
1288254721Semaste}
1289254721Semaste
1290263363SemasteOptionGroupPlatformSSH::OptionGroupPlatformSSH ()
1291263363Semaste{
1292263363Semaste}
1293263363Semaste
1294263363SemasteOptionGroupPlatformSSH::~OptionGroupPlatformSSH ()
1295263363Semaste{
1296263363Semaste}
1297263363Semaste
1298263363Semasteconst lldb_private::OptionDefinition*
1299263363SemasteOptionGroupPlatformSSH::GetDefinitions ()
1300263363Semaste{
1301263363Semaste    return g_ssh_option_table;
1302263363Semaste}
1303263363Semaste
1304263363Semastevoid
1305263363SemasteOptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter)
1306263363Semaste{
1307263363Semaste    m_ssh = false;
1308263363Semaste    m_ssh_opts.clear();
1309263363Semaste}
1310263363Semaste
1311263363Semastelldb_private::Error
1312263363SemasteOptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter,
1313263363Semaste                                          uint32_t option_idx,
1314263363Semaste                                          const char *option_arg)
1315263363Semaste{
1316263363Semaste    Error error;
1317263363Semaste    char short_option = (char) GetDefinitions()[option_idx].short_option;
1318263363Semaste    switch (short_option)
1319263363Semaste    {
1320263363Semaste        case 's':
1321263363Semaste            m_ssh = true;
1322263363Semaste            break;
1323263363Semaste
1324263363Semaste        case 'S':
1325263363Semaste            m_ssh_opts.assign(option_arg);
1326263363Semaste            break;
1327263363Semaste
1328263363Semaste        default:
1329263363Semaste            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1330263363Semaste            break;
1331263363Semaste    }
1332263363Semaste
1333263363Semaste    return error;
1334263363Semaste}
1335263363Semaste
1336263363Semasteuint32_t
1337263363SemasteOptionGroupPlatformSSH::GetNumDefinitions ()
1338263363Semaste{
1339263363Semaste    return llvm::array_lengthof(g_ssh_option_table);
1340263363Semaste}
1341263363Semaste
1342263363SemasteOptionGroupPlatformCaching::OptionGroupPlatformCaching ()
1343263363Semaste{
1344263363Semaste}
1345263363Semaste
1346263363SemasteOptionGroupPlatformCaching::~OptionGroupPlatformCaching ()
1347263363Semaste{
1348263363Semaste}
1349263363Semaste
1350263363Semasteconst lldb_private::OptionDefinition*
1351263363SemasteOptionGroupPlatformCaching::GetDefinitions ()
1352263363Semaste{
1353263363Semaste    return g_caching_option_table;
1354263363Semaste}
1355263363Semaste
1356263363Semastevoid
1357263363SemasteOptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter)
1358263363Semaste{
1359263363Semaste    m_cache_dir.clear();
1360263363Semaste}
1361263363Semaste
1362263363Semastelldb_private::Error
1363263363SemasteOptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter,
1364263363Semaste                                        uint32_t option_idx,
1365263363Semaste                                        const char *option_arg)
1366263363Semaste{
1367263363Semaste    Error error;
1368263363Semaste    char short_option = (char) GetDefinitions()[option_idx].short_option;
1369263363Semaste    switch (short_option)
1370263363Semaste    {
1371263363Semaste        case 'c':
1372263363Semaste            m_cache_dir.assign(option_arg);
1373263363Semaste            break;
1374263363Semaste
1375263363Semaste        default:
1376263363Semaste            error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1377263363Semaste            break;
1378263363Semaste    }
1379263363Semaste
1380263363Semaste    return error;
1381263363Semaste}
1382263363Semaste
1383263363Semasteuint32_t
1384263363SemasteOptionGroupPlatformCaching::GetNumDefinitions ()
1385263363Semaste{
1386263363Semaste    return llvm::array_lengthof(g_caching_option_table);
1387263363Semaste}
1388263363Semaste
1389254721Semastesize_t
1390254721SemastePlatform::GetEnvironment (StringList &environment)
1391254721Semaste{
1392254721Semaste    environment.Clear();
1393254721Semaste    return false;
1394254721Semaste}
1395269024Semaste
1396269024Semasteconst std::vector<ConstString> &
1397269024SemastePlatform::GetTrapHandlerSymbolNames ()
1398269024Semaste{
1399269024Semaste    if (!m_calculated_trap_handlers)
1400269024Semaste    {
1401269024Semaste        CalculateTrapHandlerSymbolNames();
1402269024Semaste        m_calculated_trap_handlers = true;
1403269024Semaste    }
1404269024Semaste    return m_trap_handlers;
1405269024Semaste}
1406269024Semaste
1407