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