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