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