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
26using namespace lldb;
27using namespace lldb_private;
28
29// Use a singleton function for g_local_platform_sp to avoid init
30// constructors since LLDB is often part of a shared library
31static PlatformSP&
32GetDefaultPlatformSP ()
33{
34    static PlatformSP g_default_platform_sp;
35    return g_default_platform_sp;
36}
37
38static Mutex &
39GetConnectedPlatformListMutex ()
40{
41    static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive);
42    return g_remote_connected_platforms_mutex;
43}
44static std::vector<PlatformSP> &
45GetConnectedPlatformList ()
46{
47    static std::vector<PlatformSP> g_remote_connected_platforms;
48    return g_remote_connected_platforms;
49}
50
51
52const char *
53Platform::GetHostPlatformName ()
54{
55    return "host";
56}
57
58//------------------------------------------------------------------
59/// Get the native host platform plug-in.
60///
61/// There should only be one of these for each host that LLDB runs
62/// upon that should be statically compiled in and registered using
63/// preprocessor macros or other similar build mechanisms.
64///
65/// This platform will be used as the default platform when launching
66/// or attaching to processes unless another platform is specified.
67//------------------------------------------------------------------
68PlatformSP
69Platform::GetDefaultPlatform ()
70{
71    return GetDefaultPlatformSP ();
72}
73
74void
75Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
76{
77    // The native platform should use its static void Platform::Initialize()
78    // function to register itself as the native platform.
79    GetDefaultPlatformSP () = platform_sp;
80}
81
82Error
83Platform::GetFile (const FileSpec &platform_file,
84                   const UUID *uuid_ptr,
85                   FileSpec &local_file)
86{
87    // Default to the local case
88    local_file = platform_file;
89    return Error();
90}
91
92FileSpecList
93Platform::LocateExecutableScriptingResources (Target *target, Module &module)
94{
95    return FileSpecList();
96}
97
98Platform*
99Platform::FindPlugin (Process *process, const ConstString &plugin_name)
100{
101    PlatformCreateInstance create_callback = NULL;
102    if (plugin_name)
103    {
104        create_callback  = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
105        if (create_callback)
106        {
107            ArchSpec arch;
108            if (process)
109            {
110                arch = process->GetTarget().GetArchitecture();
111            }
112            std::unique_ptr<Platform> instance_ap(create_callback(process, &arch));
113            if (instance_ap.get())
114                return instance_ap.release();
115        }
116    }
117    else
118    {
119        for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
120        {
121            std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
122            if (instance_ap.get())
123                return instance_ap.release();
124        }
125    }
126    return NULL;
127}
128
129Error
130Platform::GetSharedModule (const ModuleSpec &module_spec,
131                           ModuleSP &module_sp,
132                           const FileSpecList *module_search_paths_ptr,
133                           ModuleSP *old_module_sp_ptr,
134                           bool *did_create_ptr)
135{
136    // Don't do any path remapping for the default implementation
137    // of the platform GetSharedModule function, just call through
138    // to our static ModuleList function. Platform subclasses that
139    // implement remote debugging, might have a developer kits
140    // installed that have cached versions of the files for the
141    // remote target, or might implement a download and cache
142    // locally implementation.
143    const bool always_create = false;
144    return ModuleList::GetSharedModule (module_spec,
145                                        module_sp,
146                                        module_search_paths_ptr,
147                                        old_module_sp_ptr,
148                                        did_create_ptr,
149                                        always_create);
150}
151
152PlatformSP
153Platform::Create (const char *platform_name, Error &error)
154{
155    PlatformCreateInstance create_callback = NULL;
156    lldb::PlatformSP platform_sp;
157    if (platform_name && platform_name[0])
158    {
159        ConstString const_platform_name (platform_name);
160        create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name);
161        if (create_callback)
162            platform_sp.reset(create_callback(true, NULL));
163        else
164            error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
165    }
166    else
167        error.SetErrorString ("invalid platform name");
168    return platform_sp;
169}
170
171
172PlatformSP
173Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error)
174{
175    lldb::PlatformSP platform_sp;
176    if (arch.IsValid())
177    {
178        uint32_t idx;
179        PlatformCreateInstance create_callback;
180        // First try exact arch matches across all platform plug-ins
181        bool exact = true;
182        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
183        {
184            if (create_callback)
185            {
186                platform_sp.reset(create_callback(false, &arch));
187                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
188                    return platform_sp;
189            }
190        }
191        // Next try compatible arch matches across all platform plug-ins
192        exact = false;
193        for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx)
194        {
195            if (create_callback)
196            {
197                platform_sp.reset(create_callback(false, &arch));
198                if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr))
199                    return platform_sp;
200            }
201        }
202    }
203    else
204        error.SetErrorString ("invalid platform name");
205    if (platform_arch_ptr)
206        platform_arch_ptr->Clear();
207    platform_sp.reset();
208    return platform_sp;
209}
210
211uint32_t
212Platform::GetNumConnectedRemotePlatforms ()
213{
214    Mutex::Locker locker (GetConnectedPlatformListMutex ());
215    return GetConnectedPlatformList().size();
216}
217
218PlatformSP
219Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
220{
221    PlatformSP platform_sp;
222    {
223        Mutex::Locker locker (GetConnectedPlatformListMutex ());
224        if (idx < GetConnectedPlatformList().size())
225            platform_sp = GetConnectedPlatformList ()[idx];
226    }
227    return platform_sp;
228}
229
230//------------------------------------------------------------------
231/// Default Constructor
232//------------------------------------------------------------------
233Platform::Platform (bool is_host) :
234    m_is_host (is_host),
235    m_os_version_set_while_connected (false),
236    m_system_arch_set_while_connected (false),
237    m_sdk_sysroot (),
238    m_sdk_build (),
239    m_remote_url (),
240    m_name (),
241    m_major_os_version (UINT32_MAX),
242    m_minor_os_version (UINT32_MAX),
243    m_update_os_version (UINT32_MAX),
244    m_system_arch(),
245    m_uid_map_mutex (Mutex::eMutexTypeNormal),
246    m_gid_map_mutex (Mutex::eMutexTypeNormal),
247    m_uid_map(),
248    m_gid_map(),
249    m_max_uid_name_len (0),
250    m_max_gid_name_len (0)
251{
252    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
253    if (log)
254        log->Printf ("%p Platform::Platform()", this);
255}
256
257//------------------------------------------------------------------
258/// Destructor.
259///
260/// The destructor is virtual since this class is designed to be
261/// inherited from by the plug-in instance.
262//------------------------------------------------------------------
263Platform::~Platform()
264{
265    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
266    if (log)
267        log->Printf ("%p Platform::~Platform()", this);
268}
269
270void
271Platform::GetStatus (Stream &strm)
272{
273    uint32_t major = UINT32_MAX;
274    uint32_t minor = UINT32_MAX;
275    uint32_t update = UINT32_MAX;
276    std::string s;
277    strm.Printf ("  Platform: %s\n", GetPluginName().GetCString());
278
279    ArchSpec arch (GetSystemArchitecture());
280    if (arch.IsValid())
281    {
282        if (!arch.GetTriple().str().empty())
283        strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
284    }
285
286    if (GetOSVersion(major, minor, update))
287    {
288        strm.Printf("OS Version: %u", major);
289        if (minor != UINT32_MAX)
290            strm.Printf(".%u", minor);
291        if (update != UINT32_MAX)
292            strm.Printf(".%u", update);
293
294        if (GetOSBuildString (s))
295            strm.Printf(" (%s)", s.c_str());
296
297        strm.EOL();
298    }
299
300    if (GetOSKernelDescription (s))
301        strm.Printf("    Kernel: %s\n", s.c_str());
302
303    if (IsHost())
304    {
305        strm.Printf("  Hostname: %s\n", GetHostname());
306    }
307    else
308    {
309        const bool is_connected = IsConnected();
310        if (is_connected)
311            strm.Printf("  Hostname: %s\n", GetHostname());
312        strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
313    }
314}
315
316
317bool
318Platform::GetOSVersion (uint32_t &major,
319                        uint32_t &minor,
320                        uint32_t &update)
321{
322    bool success = m_major_os_version != UINT32_MAX;
323    if (IsHost())
324    {
325        if (!success)
326        {
327            // We have a local host platform
328            success = Host::GetOSVersion (m_major_os_version,
329                                          m_minor_os_version,
330                                          m_update_os_version);
331            m_os_version_set_while_connected = success;
332        }
333    }
334    else
335    {
336        // We have a remote platform. We can only fetch the remote
337        // OS version if we are connected, and we don't want to do it
338        // more than once.
339
340        const bool is_connected = IsConnected();
341
342        bool fetch = false;
343        if (success)
344        {
345            // We have valid OS version info, check to make sure it wasn't
346            // manually set prior to connecting. If it was manually set prior
347            // to connecting, then lets fetch the actual OS version info
348            // if we are now connected.
349            if (is_connected && !m_os_version_set_while_connected)
350                fetch = true;
351        }
352        else
353        {
354            // We don't have valid OS version info, fetch it if we are connected
355            fetch = is_connected;
356        }
357
358        if (fetch)
359        {
360            success = GetRemoteOSVersion ();
361            m_os_version_set_while_connected = success;
362        }
363    }
364
365    if (success)
366    {
367        major = m_major_os_version;
368        minor = m_minor_os_version;
369        update = m_update_os_version;
370    }
371    return success;
372}
373
374bool
375Platform::GetOSBuildString (std::string &s)
376{
377    if (IsHost())
378        return Host::GetOSBuildString (s);
379    else
380        return GetRemoteOSBuildString (s);
381}
382
383bool
384Platform::GetOSKernelDescription (std::string &s)
385{
386    if (IsHost())
387        return Host::GetOSKernelDescription (s);
388    else
389        return GetRemoteOSKernelDescription (s);
390}
391
392ConstString
393Platform::GetName ()
394{
395    const char *name = GetHostname();
396    if (name == NULL || name[0] == '\0')
397        return GetPluginName();
398    return ConstString (name);
399}
400
401const char *
402Platform::GetHostname ()
403{
404    if (IsHost())
405        return "localhost";
406
407    if (m_name.empty())
408        return NULL;
409    return m_name.c_str();
410}
411
412const char *
413Platform::GetUserName (uint32_t uid)
414{
415    const char *user_name = GetCachedUserName(uid);
416    if (user_name)
417        return user_name;
418    if (IsHost())
419    {
420        std::string name;
421        if (Host::GetUserName(uid, name))
422            return SetCachedUserName (uid, name.c_str(), name.size());
423    }
424    return NULL;
425}
426
427const char *
428Platform::GetGroupName (uint32_t gid)
429{
430    const char *group_name = GetCachedGroupName(gid);
431    if (group_name)
432        return group_name;
433    if (IsHost())
434    {
435        std::string name;
436        if (Host::GetGroupName(gid, name))
437            return SetCachedGroupName (gid, name.c_str(), name.size());
438    }
439    return NULL;
440}
441
442bool
443Platform::SetOSVersion (uint32_t major,
444                        uint32_t minor,
445                        uint32_t update)
446{
447    if (IsHost())
448    {
449        // We don't need anyone setting the OS version for the host platform,
450        // we should be able to figure it out by calling Host::GetOSVersion(...).
451        return false;
452    }
453    else
454    {
455        // We have a remote platform, allow setting the target OS version if
456        // we aren't connected, since if we are connected, we should be able to
457        // request the remote OS version from the connected platform.
458        if (IsConnected())
459            return false;
460        else
461        {
462            // We aren't connected and we might want to set the OS version
463            // ahead of time before we connect so we can peruse files and
464            // use a local SDK or PDK cache of support files to disassemble
465            // or do other things.
466            m_major_os_version = major;
467            m_minor_os_version = minor;
468            m_update_os_version = update;
469            return true;
470        }
471    }
472    return false;
473}
474
475
476Error
477Platform::ResolveExecutable (const FileSpec &exe_file,
478                             const ArchSpec &exe_arch,
479                             lldb::ModuleSP &exe_module_sp,
480                             const FileSpecList *module_search_paths_ptr)
481{
482    Error error;
483    if (exe_file.Exists())
484    {
485        ModuleSpec module_spec (exe_file, exe_arch);
486        if (module_spec.GetArchitecture().IsValid())
487        {
488            error = ModuleList::GetSharedModule (module_spec,
489                                                 exe_module_sp,
490                                                 module_search_paths_ptr,
491                                                 NULL,
492                                                 NULL);
493        }
494        else
495        {
496            // No valid architecture was specified, ask the platform for
497            // the architectures that we should be using (in the correct order)
498            // and see if we can find a match that way
499            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx)
500            {
501                error = ModuleList::GetSharedModule (module_spec,
502                                                     exe_module_sp,
503                                                     module_search_paths_ptr,
504                                                     NULL,
505                                                     NULL);
506                // Did we find an executable using one of the
507                if (error.Success() && exe_module_sp)
508                    break;
509            }
510        }
511    }
512    else
513    {
514        error.SetErrorStringWithFormat ("'%s' does not exist",
515                                        exe_file.GetPath().c_str());
516    }
517    return error;
518}
519
520Error
521Platform::ResolveSymbolFile (Target &target,
522                             const ModuleSpec &sym_spec,
523                             FileSpec &sym_file)
524{
525    Error error;
526    if (sym_spec.GetSymbolFileSpec().Exists())
527        sym_file = sym_spec.GetSymbolFileSpec();
528    else
529        error.SetErrorString("unable to resolve symbol file");
530    return error;
531
532}
533
534
535
536bool
537Platform::ResolveRemotePath (const FileSpec &platform_path,
538                             FileSpec &resolved_platform_path)
539{
540    resolved_platform_path = platform_path;
541    return resolved_platform_path.ResolvePath();
542}
543
544
545const ArchSpec &
546Platform::GetSystemArchitecture()
547{
548    if (IsHost())
549    {
550        if (!m_system_arch.IsValid())
551        {
552            // We have a local host platform
553            m_system_arch = Host::GetArchitecture();
554            m_system_arch_set_while_connected = m_system_arch.IsValid();
555        }
556    }
557    else
558    {
559        // We have a remote platform. We can only fetch the remote
560        // system architecture if we are connected, and we don't want to do it
561        // more than once.
562
563        const bool is_connected = IsConnected();
564
565        bool fetch = false;
566        if (m_system_arch.IsValid())
567        {
568            // We have valid OS version info, check to make sure it wasn't
569            // manually set prior to connecting. If it was manually set prior
570            // to connecting, then lets fetch the actual OS version info
571            // if we are now connected.
572            if (is_connected && !m_system_arch_set_while_connected)
573                fetch = true;
574        }
575        else
576        {
577            // We don't have valid OS version info, fetch it if we are connected
578            fetch = is_connected;
579        }
580
581        if (fetch)
582        {
583            m_system_arch = GetRemoteSystemArchitecture ();
584            m_system_arch_set_while_connected = m_system_arch.IsValid();
585        }
586    }
587    return m_system_arch;
588}
589
590
591Error
592Platform::ConnectRemote (Args& args)
593{
594    Error error;
595    if (IsHost())
596        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
597    else
598        error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString());
599    return error;
600}
601
602Error
603Platform::DisconnectRemote ()
604{
605    Error error;
606    if (IsHost())
607        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString());
608    else
609        error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString());
610    return error;
611}
612
613bool
614Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
615{
616    // Take care of the host case so that each subclass can just
617    // call this function to get the host functionality.
618    if (IsHost())
619        return Host::GetProcessInfo (pid, process_info);
620    return false;
621}
622
623uint32_t
624Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
625                         ProcessInstanceInfoList &process_infos)
626{
627    // Take care of the host case so that each subclass can just
628    // call this function to get the host functionality.
629    uint32_t match_count = 0;
630    if (IsHost())
631        match_count = Host::FindProcesses (match_info, process_infos);
632    return match_count;
633}
634
635
636Error
637Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
638{
639    Error error;
640    // Take care of the host case so that each subclass can just
641    // call this function to get the host functionality.
642    if (IsHost())
643    {
644        if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
645            launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
646
647        if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
648        {
649            const bool is_localhost = true;
650            const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);
651            const bool first_arg_is_full_shell_command = false;
652            if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
653                                                                  is_localhost,
654                                                                  will_debug,
655                                                                  first_arg_is_full_shell_command))
656                return error;
657        }
658
659        error = Host::LaunchProcess (launch_info);
660    }
661    else
662        error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
663    return error;
664}
665
666lldb::ProcessSP
667Platform::DebugProcess (ProcessLaunchInfo &launch_info,
668                        Debugger &debugger,
669                        Target *target,       // Can be NULL, if NULL create a new target, else use existing one
670                        Listener &listener,
671                        Error &error)
672{
673    ProcessSP process_sp;
674    // Make sure we stop at the entry point
675    launch_info.GetFlags ().Set (eLaunchFlagDebug);
676    // We always launch the process we are going to debug in a separate process
677    // group, since then we can handle ^C interrupts ourselves w/o having to worry
678    // about the target getting them as well.
679    launch_info.SetLaunchInSeparateProcessGroup(true);
680
681    error = LaunchProcess (launch_info);
682    if (error.Success())
683    {
684        if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
685        {
686            ProcessAttachInfo attach_info (launch_info);
687            process_sp = Attach (attach_info, debugger, target, listener, error);
688            if (process_sp)
689            {
690                // Since we attached to the process, it will think it needs to detach
691                // if the process object just goes away without an explicit call to
692                // Process::Kill() or Process::Detach(), so let it know to kill the
693                // process if this happens.
694                process_sp->SetShouldDetach (false);
695
696                // If we didn't have any file actions, the pseudo terminal might
697                // have been used where the slave side was given as the file to
698                // open for stdin/out/err after we have already opened the master
699                // so we can read/write stdin/out/err.
700                int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
701                if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
702                {
703                    process_sp->SetSTDIOFileDescriptor(pty_fd);
704                }
705            }
706        }
707    }
708    return process_sp;
709}
710
711
712lldb::PlatformSP
713Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr)
714{
715    lldb::PlatformSP platform_sp;
716    Error error;
717    if (arch.IsValid())
718        platform_sp = Platform::Create (arch, platform_arch_ptr, error);
719    return platform_sp;
720}
721
722
723//------------------------------------------------------------------
724/// Lets a platform answer if it is compatible with a given
725/// architecture and the target triple contained within.
726//------------------------------------------------------------------
727bool
728Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr)
729{
730    // If the architecture is invalid, we must answer true...
731    if (arch.IsValid())
732    {
733        ArchSpec platform_arch;
734        // Try for an exact architecture match first.
735        if (exact_arch_match)
736        {
737            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
738            {
739                if (arch.IsExactMatch(platform_arch))
740                {
741                    if (compatible_arch_ptr)
742                        *compatible_arch_ptr = platform_arch;
743                    return true;
744                }
745            }
746        }
747        else
748        {
749            for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx)
750            {
751                if (arch.IsCompatibleMatch(platform_arch))
752                {
753                    if (compatible_arch_ptr)
754                        *compatible_arch_ptr = platform_arch;
755                    return true;
756                }
757            }
758        }
759    }
760    if (compatible_arch_ptr)
761        compatible_arch_ptr->Clear();
762    return false;
763
764}
765
766
767lldb::BreakpointSP
768Platform::SetThreadCreationBreakpoint (lldb_private::Target &target)
769{
770    return lldb::BreakpointSP();
771}
772
773size_t
774Platform::GetEnvironment (StringList &environment)
775{
776    environment.Clear();
777    return false;
778}
779
780