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