Platform.cpp revision 5e342f50b42b265d8568e1c926328858e74b2c0a
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_remote_url (),
165    m_name (),
166    m_major_os_version (UINT32_MAX),
167    m_minor_os_version (UINT32_MAX),
168    m_update_os_version (UINT32_MAX),
169    m_system_arch(),
170    m_uid_map_mutex (Mutex::eMutexTypeNormal),
171    m_gid_map_mutex (Mutex::eMutexTypeNormal),
172    m_uid_map(),
173    m_gid_map(),
174    m_max_uid_name_len (0),
175    m_max_gid_name_len (0)
176{
177    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
178    if (log)
179        log->Printf ("%p Platform::Platform()", this);
180}
181
182//------------------------------------------------------------------
183/// Destructor.
184///
185/// The destructor is virtual since this class is designed to be
186/// inherited from by the plug-in instance.
187//------------------------------------------------------------------
188Platform::~Platform()
189{
190    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
191    if (log)
192        log->Printf ("%p Platform::~Platform()", this);
193}
194
195void
196Platform::GetStatus (Stream &strm)
197{
198    uint32_t major = UINT32_MAX;
199    uint32_t minor = UINT32_MAX;
200    uint32_t update = UINT32_MAX;
201    std::string s;
202    strm.Printf ("  Platform: %s\n", GetShortPluginName());
203
204    ArchSpec arch (GetSystemArchitecture());
205    if (arch.IsValid())
206    {
207        if (!arch.GetTriple().str().empty())
208        strm.Printf("    Triple: %s\n", arch.GetTriple().str().c_str());
209    }
210
211    if (GetOSVersion(major, minor, update))
212    {
213        strm.Printf("OS Version: %u", major);
214        if (minor != UINT32_MAX)
215            strm.Printf(".%u", minor);
216        if (update != UINT32_MAX)
217            strm.Printf(".%u", update);
218
219        if (GetOSBuildString (s))
220            strm.Printf(" (%s)", s.c_str());
221
222        strm.EOL();
223    }
224
225    if (GetOSKernelDescription (s))
226        strm.Printf("    Kernel: %s\n", s.c_str());
227
228    if (IsHost())
229    {
230        strm.Printf("  Hostname: %s\n", GetHostname());
231    }
232    else
233    {
234        const bool is_connected = IsConnected();
235        if (is_connected)
236            strm.Printf("  Hostname: %s\n", GetHostname());
237        strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
238    }
239}
240
241
242bool
243Platform::GetOSVersion (uint32_t &major,
244                        uint32_t &minor,
245                        uint32_t &update)
246{
247    bool success = m_major_os_version != UINT32_MAX;
248    if (IsHost())
249    {
250        if (!success)
251        {
252            // We have a local host platform
253            success = Host::GetOSVersion (m_major_os_version,
254                                          m_minor_os_version,
255                                          m_update_os_version);
256            m_os_version_set_while_connected = success;
257        }
258    }
259    else
260    {
261        // We have a remote platform. We can only fetch the remote
262        // OS version if we are connected, and we don't want to do it
263        // more than once.
264
265        const bool is_connected = IsConnected();
266
267        bool fetch = false;
268        if (success)
269        {
270            // We have valid OS version info, check to make sure it wasn't
271            // manually set prior to connecting. If it was manually set prior
272            // to connecting, then lets fetch the actual OS version info
273            // if we are now connected.
274            if (is_connected && !m_os_version_set_while_connected)
275                fetch = true;
276        }
277        else
278        {
279            // We don't have valid OS version info, fetch it if we are connected
280            fetch = is_connected;
281        }
282
283        if (fetch)
284        {
285            success = GetRemoteOSVersion ();
286            m_os_version_set_while_connected = success;
287        }
288    }
289
290    if (success)
291    {
292        major = m_major_os_version;
293        minor = m_minor_os_version;
294        update = m_update_os_version;
295    }
296    return success;
297}
298
299bool
300Platform::GetOSBuildString (std::string &s)
301{
302    if (IsHost())
303        return Host::GetOSBuildString (s);
304    else
305        return GetRemoteOSBuildString (s);
306}
307
308bool
309Platform::GetOSKernelDescription (std::string &s)
310{
311    if (IsHost())
312        return Host::GetOSKernelDescription (s);
313    else
314        return GetRemoteOSKernelDescription (s);
315}
316
317const char *
318Platform::GetName ()
319{
320    const char *name = GetHostname();
321    if (name == NULL || name[0] == '\0')
322        name = GetShortPluginName();
323    return name;
324}
325
326const char *
327Platform::GetHostname ()
328{
329    if (IsHost())
330        return "localhost";
331
332    if (m_name.empty())
333        return NULL;
334    return m_name.c_str();
335}
336
337const char *
338Platform::GetUserName (uint32_t uid)
339{
340    const char *user_name = GetCachedUserName(uid);
341    if (user_name)
342        return user_name;
343    if (IsHost())
344    {
345        std::string name;
346        if (Host::GetUserName(uid, name))
347            return SetCachedUserName (uid, name.c_str(), name.size());
348    }
349    return NULL;
350}
351
352const char *
353Platform::GetGroupName (uint32_t gid)
354{
355    const char *group_name = GetCachedGroupName(gid);
356    if (group_name)
357        return group_name;
358    if (IsHost())
359    {
360        std::string name;
361        if (Host::GetGroupName(gid, name))
362            return SetCachedGroupName (gid, name.c_str(), name.size());
363    }
364    return NULL;
365}
366
367bool
368Platform::SetOSVersion (uint32_t major,
369                        uint32_t minor,
370                        uint32_t update)
371{
372    if (IsHost())
373    {
374        // We don't need anyone setting the OS version for the host platform,
375        // we should be able to figure it out by calling Host::GetOSVersion(...).
376        return false;
377    }
378    else
379    {
380        // We have a remote platform, allow setting the target OS version if
381        // we aren't connected, since if we are connected, we should be able to
382        // request the remote OS version from the connected platform.
383        if (IsConnected())
384            return false;
385        else
386        {
387            // We aren't connected and we might want to set the OS version
388            // ahead of time before we connect so we can peruse files and
389            // use a local SDK or PDK cache of support files to disassemble
390            // or do other things.
391            m_major_os_version = major;
392            m_minor_os_version = minor;
393            m_update_os_version = update;
394            return true;
395        }
396    }
397    return false;
398}
399
400
401Error
402Platform::ResolveExecutable (const FileSpec &exe_file,
403                             const ArchSpec &exe_arch,
404                             lldb::ModuleSP &exe_module_sp)
405{
406    Error error;
407    if (exe_file.Exists())
408    {
409        if (exe_arch.IsValid())
410        {
411            error = ModuleList::GetSharedModule (exe_file,
412                                                 exe_arch,
413                                                 NULL,
414                                                 NULL,
415                                                 0,
416                                                 exe_module_sp,
417                                                 NULL,
418                                                 NULL);
419        }
420        else
421        {
422            // No valid architecture was specified, ask the platform for
423            // the architectures that we should be using (in the correct order)
424            // and see if we can find a match that way
425            ArchSpec platform_arch;
426            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
427            {
428                error = ModuleList::GetSharedModule (exe_file,
429                                                     platform_arch,
430                                                     NULL,
431                                                     NULL,
432                                                     0,
433                                                     exe_module_sp,
434                                                     NULL,
435                                                     NULL);
436                // Did we find an executable using one of the
437                if (error.Success() && exe_module_sp)
438                    break;
439            }
440        }
441    }
442    else
443    {
444        error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
445                                        exe_file.GetDirectory().AsCString(""),
446                                        exe_file.GetDirectory() ? "/" : "",
447                                        exe_file.GetFilename().AsCString(""));
448    }
449    return error;
450}
451
452
453const ArchSpec &
454Platform::GetSystemArchitecture()
455{
456    if (IsHost())
457    {
458        if (!m_system_arch.IsValid())
459        {
460            // We have a local host platform
461            m_system_arch = Host::GetArchitecture();
462            m_system_arch_set_while_connected = m_system_arch.IsValid();
463        }
464    }
465    else
466    {
467        // We have a remote platform. We can only fetch the remote
468        // system architecture if we are connected, and we don't want to do it
469        // more than once.
470
471        const bool is_connected = IsConnected();
472
473        bool fetch = false;
474        if (m_system_arch.IsValid())
475        {
476            // We have valid OS version info, check to make sure it wasn't
477            // manually set prior to connecting. If it was manually set prior
478            // to connecting, then lets fetch the actual OS version info
479            // if we are now connected.
480            if (is_connected && !m_system_arch_set_while_connected)
481                fetch = true;
482        }
483        else
484        {
485            // We don't have valid OS version info, fetch it if we are connected
486            fetch = is_connected;
487        }
488
489        if (fetch)
490        {
491            m_system_arch = GetRemoteSystemArchitecture ();
492            m_system_arch_set_while_connected = m_system_arch.IsValid();
493        }
494    }
495    return m_system_arch;
496}
497
498
499Error
500Platform::ConnectRemote (Args& args)
501{
502    Error error;
503    if (IsHost())
504        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
505    else
506        error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
507    return error;
508}
509
510Error
511Platform::DisconnectRemote ()
512{
513    Error error;
514    if (IsHost())
515        error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
516    else
517        error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
518    return error;
519}
520
521bool
522Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
523{
524    // Take care of the host case so that each subclass can just
525    // call this function to get the host functionality.
526    if (IsHost())
527        return Host::GetProcessInfo (pid, process_info);
528    return false;
529}
530
531uint32_t
532Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
533                         ProcessInstanceInfoList &process_infos)
534{
535    // Take care of the host case so that each subclass can just
536    // call this function to get the host functionality.
537    uint32_t match_count = 0;
538    if (IsHost())
539        match_count = Host::FindProcesses (match_info, process_infos);
540    return match_count;
541}
542
543
544Error
545Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
546{
547    Error error;
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        error = Host::LaunchProcess (launch_info);
552    else
553        error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
554    return error;
555}
556
557lldb::ProcessSP
558Platform::DebugProcess (ProcessLaunchInfo &launch_info,
559                        Debugger &debugger,
560                        Target *target,       // Can be NULL, if NULL create a new target, else use existing one
561                        Listener &listener,
562                        Error &error)
563{
564    ProcessSP process_sp;
565    // Make sure we stop at the entry point
566    launch_info.GetFlags ().Set (eLaunchFlagDebug);
567    error = LaunchProcess (launch_info);
568    if (error.Success())
569    {
570        lldb::pid_t pid = launch_info.GetProcessID();
571        if (pid != LLDB_INVALID_PROCESS_ID)
572        {
573            process_sp = Attach (pid, debugger, target, listener, error);
574
575//            if (process_sp)
576//            {
577//                if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
578//                    process_sp->Resume();
579//            }
580        }
581    }
582    return process_sp;
583}
584
585