Platform.h revision 604f0d336f0d9390a0405022ef660ae922ef29bf
1//===-- Platform.h ----------------------------------------------*- 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#ifndef liblldb_Platform_h_
11#define liblldb_Platform_h_
12
13// C Includes
14// C++ Includes
15#include <map>
16#include <string>
17#include <vector>
18
19// Other libraries and framework includes
20// Project includes
21#include "lldb/lldb-public.h"
22#include "lldb/Core/ArchSpec.h"
23#include "lldb/Core/ConstString.h"
24#include "lldb/Core/PluginInterface.h"
25#include "lldb/Host/Mutex.h"
26
27namespace lldb_private {
28
29    //----------------------------------------------------------------------
30    /// @class Platform Platform.h "lldb/Target/Platform.h"
31    /// @brief A plug-in interface definition class for debug platform that
32    /// includes many platform abilities such as:
33    ///     @li getting platform information such as supported architectures,
34    ///         supported binary file formats and more
35    ///     @li launching new processes
36    ///     @li attaching to existing processes
37    ///     @li download/upload files
38    ///     @li execute shell commands
39    ///     @li listing and getting info for existing processes
40    ///     @li attaching and possibly debugging the platform's kernel
41    //----------------------------------------------------------------------
42    class Platform : public PluginInterface
43    {
44    public:
45
46        //------------------------------------------------------------------
47        /// Get the native host platform plug-in.
48        ///
49        /// There should only be one of these for each host that LLDB runs
50        /// upon that should be statically compiled in and registered using
51        /// preprocessor macros or other similar build mechanisms in a
52        /// PlatformSubclass::Initialize() function.
53        ///
54        /// This platform will be used as the default platform when launching
55        /// or attaching to processes unless another platform is specified.
56        //------------------------------------------------------------------
57        static lldb::PlatformSP
58        GetDefaultPlatform ();
59
60        static const char *
61        GetHostPlatformName ();
62
63        static void
64        SetDefaultPlatform (const lldb::PlatformSP &platform_sp);
65
66        static lldb::PlatformSP
67        Create (const char *platform_name, Error &error);
68
69        static uint32_t
70        GetNumConnectedRemotePlatforms ();
71
72        static lldb::PlatformSP
73        GetConnectedRemotePlatformAtIndex (uint32_t idx);
74
75        //------------------------------------------------------------------
76        /// Default Constructor
77        //------------------------------------------------------------------
78        Platform (bool is_host_platform);
79
80        //------------------------------------------------------------------
81        /// Destructor.
82        ///
83        /// The destructor is virtual since this class is designed to be
84        /// inherited from by the plug-in instance.
85        //------------------------------------------------------------------
86        virtual
87        ~Platform();
88
89        //------------------------------------------------------------------
90        /// Set the target's executable based off of the existing
91        /// architecture information in \a target given a path to an
92        /// executable \a exe_file.
93        ///
94        /// Each platform knows the architectures that it supports and can
95        /// select the correct architecture slice within \a exe_file by
96        /// inspecting the architecture in \a target. If the target had an
97        /// architecture specified, then in can try and obey that request
98        /// and optionally fail if the architecture doesn't match up.
99        /// If no architecture is specified, the platform should select the
100        /// default architecture from \a exe_file. Any application bundles
101        /// or executable wrappers can also be inspected for the actual
102        /// application binary within the bundle that should be used.
103        ///
104        /// @return
105        ///     Returns \b true if this Platform plug-in was able to find
106        ///     a suitable executable, \b false otherwise.
107        //------------------------------------------------------------------
108        virtual Error
109        ResolveExecutable (const FileSpec &exe_file,
110                           const ArchSpec &arch,
111                           lldb::ModuleSP &module_sp);
112
113        bool
114        GetOSVersion (uint32_t &major,
115                      uint32_t &minor,
116                      uint32_t &update);
117
118        bool
119        SetOSVersion (uint32_t major,
120                      uint32_t minor,
121                      uint32_t update);
122
123        bool
124        GetOSBuildString (std::string &s);
125
126        bool
127        GetOSKernelDescription (std::string &s);
128
129        // Returns the the hostname if we are connected, else the short plugin
130        // name.
131        const char *
132        GetName ();
133
134        virtual const char *
135        GetHostname ();
136
137        virtual const char *
138        GetDescription () = 0;
139
140        //------------------------------------------------------------------
141        /// Report the current status for this platform.
142        ///
143        /// The returned string usually involves returning the OS version
144        /// (if available), and any SDK directory that might be being used
145        /// for local file caching, and if connected a quick blurb about
146        /// what this platform is connected to.
147        //------------------------------------------------------------------
148        virtual void
149        GetStatus (Stream &strm);
150
151        //------------------------------------------------------------------
152        // Subclasses must be able to fetch the current OS version
153        //
154        // Remote classes must be connected for this to succeed. Local
155        // subclasses don't need to override this function as it will just
156        // call the Host::GetOSVersion().
157        //------------------------------------------------------------------
158        virtual bool
159        GetRemoteOSVersion ()
160        {
161            return false;
162        }
163
164        virtual bool
165        GetRemoteOSBuildString (std::string &s)
166        {
167            s.clear();
168            return false;
169        }
170
171        virtual bool
172        GetRemoteOSKernelDescription (std::string &s)
173        {
174            s.clear();
175            return false;
176        }
177
178        // Remote Platform subclasses need to override this function
179        virtual ArchSpec
180        GetRemoteSystemArchitecture ()
181        {
182            return ArchSpec(); // Return an invalid architecture
183        }
184
185        virtual const char *
186        GetUserName (uint32_t uid);
187
188        virtual const char *
189        GetGroupName (uint32_t gid);
190
191        //------------------------------------------------------------------
192        /// Locate a file for a platform.
193        ///
194        /// The default implementation of this function will return the same
195        /// file patch in \a local_file as was in \a platform_file.
196        ///
197        /// @param[in] platform_file
198        ///     The platform file path to locate and cache locally.
199        ///
200        /// @param[in] uuid_ptr
201        ///     If we know the exact UUID of the file we are looking for, it
202        ///     can be specified. If it is not specified, we might now know
203        ///     the exact file. The UUID is usually some sort of MD5 checksum
204        ///     for the file and is sometimes known by dynamic linkers/loaders.
205        ///     If the UUID is known, it is best to supply it to platform
206        ///     file queries to ensure we are finding the correct file, not
207        ///     just a file at the correct path.
208        ///
209        /// @param[out] local_file
210        ///     A locally cached version of the platform file. For platforms
211        ///     that describe the current host computer, this will just be
212        ///     the same file. For remote platforms, this file might come from
213        ///     and SDK directory, or might need to be sync'ed over to the
214        ///     current machine for efficient debugging access.
215        ///
216        /// @return
217        ///     An error object.
218        //------------------------------------------------------------------
219        virtual Error
220        GetFile (const FileSpec &platform_file,
221                 const UUID *uuid_ptr,
222                 FileSpec &local_file);
223
224        virtual Error
225        GetSharedModule (const FileSpec &platform_file,
226                         const ArchSpec &arch,
227                         const UUID *uuid_ptr,
228                         const ConstString *object_name_ptr,
229                         off_t object_offset,
230                         lldb::ModuleSP &module_sp,
231                         lldb::ModuleSP *old_module_sp_ptr,
232                         bool *did_create_ptr);
233
234        virtual Error
235        ConnectRemote (Args& args);
236
237        virtual Error
238        DisconnectRemote ();
239
240        //------------------------------------------------------------------
241        /// Get the platform's supported architectures in the order in which
242        /// they should be searched.
243        ///
244        /// @param[in] idx
245        ///     A zero based architecture index
246        ///
247        /// @param[out] arch
248        ///     A copy of the archgitecture at index if the return value is
249        ///     \b true.
250        ///
251        /// @return
252        ///     \b true if \a arch was filled in and is valid, \b false
253        ///     otherwise.
254        //------------------------------------------------------------------
255        virtual bool
256        GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) = 0;
257
258        virtual size_t
259        GetSoftwareBreakpointTrapOpcode (Target &target,
260                                         BreakpointSite *bp_site) = 0;
261
262        //------------------------------------------------------------------
263        /// Launch a new process on a platform, not necessarily for
264        /// debugging, it could be just for running the process.
265        //------------------------------------------------------------------
266        virtual Error
267        LaunchProcess (ProcessLaunchInfo &launch_info);
268
269        //------------------------------------------------------------------
270        /// Subclasses should NOT need to implement this function as it uses
271        /// the Platform::LaunchProcess() followed by Platform::Attach ()
272        //------------------------------------------------------------------
273        lldb::ProcessSP
274        DebugProcess (ProcessLaunchInfo &launch_info,
275                      Debugger &debugger,
276                      Target *target,       // Can be NULL, if NULL create a new target, else use existing one
277                      Listener &listener,
278                      Error &error);
279
280        //------------------------------------------------------------------
281        /// Attach to an existing process using a process ID.
282        ///
283        /// Each platform subclass needs to implement this function and
284        /// attempt to attach to the process with the process ID of \a pid.
285        /// The platform subclass should return an appropriate ProcessSP
286        /// subclass that is attached to the process, or an empty shared
287        /// pointer with an appriopriate error.
288        ///
289        /// @param[in] pid
290        ///     The process ID that we should attempt to attach to.
291        ///
292        /// @return
293        ///     An appropriate ProcessSP containing a valid shared pointer
294        ///     to the default Process subclass for the platform that is
295        ///     attached to the process, or an empty shared pointer with an
296        ///     appriopriate error fill into the \a error object.
297        //------------------------------------------------------------------
298        virtual lldb::ProcessSP
299        Attach (lldb::pid_t pid,
300                Debugger &debugger,
301                Target *target,       // Can be NULL, if NULL create a new target, else use existing one
302                Listener &listener,
303                Error &error) = 0;
304
305        //------------------------------------------------------------------
306        /// Attach to an existing process by process name.
307        ///
308        /// This function is not meant to be overridden by Process
309        /// subclasses. It will first call
310        /// Process::WillAttach (const char *) and if that returns \b
311        /// true, Process::DoAttach (const char *) will be called to
312        /// actually do the attach. If DoAttach returns \b true, then
313        /// Process::DidAttach() will be called.
314        ///
315        /// @param[in] process_name
316        ///     A process name to match against the current process list.
317        ///
318        /// @return
319        ///     Returns \a pid if attaching was successful, or
320        ///     LLDB_INVALID_PROCESS_ID if attaching fails.
321        //------------------------------------------------------------------
322//        virtual lldb::ProcessSP
323//        Attach (const char *process_name,
324//                bool wait_for_launch,
325//                Error &error) = 0;
326
327        //------------------------------------------------------------------
328        // The base class Platform will take care of the host platform.
329        // Subclasses will need to fill in the remote case.
330        //------------------------------------------------------------------
331        virtual uint32_t
332        FindProcesses (const ProcessInstanceInfoMatch &match_info,
333                       ProcessInstanceInfoList &proc_infos);
334
335        virtual bool
336        GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
337
338        const std::string &
339        GetRemoteURL () const
340        {
341            return m_remote_url;
342        }
343
344        bool
345        IsHost () const
346        {
347            return m_is_host;    // Is this the default host platform?
348        }
349
350        bool
351        IsRemote () const
352        {
353            return !m_is_host;
354        }
355
356        virtual bool
357        IsConnected () const
358        {
359            // Remote subclasses should override this function
360            return IsHost();
361        }
362
363        const ArchSpec &
364        GetSystemArchitecture();
365
366        void
367        SetSystemArchitecture (const ArchSpec &arch)
368        {
369            m_system_arch = arch;
370            if (IsHost())
371                m_os_version_set_while_connected = m_system_arch.IsValid();
372        }
373
374        // Used for column widths
375        uint32_t
376        GetMaxUserIDNameLength() const
377        {
378            return m_max_uid_name_len;
379        }
380        // Used for column widths
381        uint32_t
382        GetMaxGroupIDNameLength() const
383        {
384            return m_max_gid_name_len;
385        }
386
387        const ConstString &
388        GetSDKRootDirectory () const
389        {
390            return m_sdk_sysroot;
391        }
392
393        void
394        SetSDKRootDirectory (const ConstString &dir)
395        {
396            m_sdk_sysroot = dir;
397        }
398
399        const ConstString &
400        GetSDKBuild () const
401        {
402            return m_sdk_build;
403        }
404
405        void
406        SetSDKBuild (const ConstString &sdk_build)
407        {
408            m_sdk_build = sdk_build;
409        }
410
411
412    protected:
413        bool m_is_host;
414        // Set to true when we are able to actually set the OS version while
415        // being connected. For remote platforms, we might set the version ahead
416        // of time before we actually connect and this version might change when
417        // we actually connect to a remote platform. For the host platform this
418        // will be set to the once we call Host::GetOSVersion().
419        bool m_os_version_set_while_connected;
420        bool m_system_arch_set_while_connected;
421        ConstString m_sdk_sysroot; // the root location of where the SDK files are all located
422        ConstString m_sdk_build;
423        std::string m_remote_url;
424        std::string m_name;
425        uint32_t m_major_os_version;
426        uint32_t m_minor_os_version;
427        uint32_t m_update_os_version;
428        ArchSpec m_system_arch; // The architecture of the kernel or the remote platform
429        typedef std::map<uint32_t, ConstString> IDToNameMap;
430        Mutex m_uid_map_mutex;
431        Mutex m_gid_map_mutex;
432        IDToNameMap m_uid_map;
433        IDToNameMap m_gid_map;
434        uint32_t m_max_uid_name_len;
435        uint32_t m_max_gid_name_len;
436
437        const char *
438        GetCachedUserName (uint32_t uid)
439        {
440            Mutex::Locker locker (m_uid_map_mutex);
441            IDToNameMap::iterator pos = m_uid_map.find (uid);
442            if (pos != m_uid_map.end())
443            {
444                // return the empty string if our string is NULL
445                // so we can tell when things were in the negative
446                // cached (didn't find a valid user name, don't keep
447                // trying)
448                return pos->second.AsCString("");
449            }
450            return NULL;
451        }
452
453        const char *
454        SetCachedUserName (uint32_t uid, const char *name, size_t name_len)
455        {
456            Mutex::Locker locker (m_uid_map_mutex);
457            ConstString const_name (name);
458            m_uid_map[uid] = const_name;
459            if (m_max_uid_name_len < name_len)
460                m_max_uid_name_len = name_len;
461            // Const strings lives forever in our const string pool, so we can return the const char *
462            return const_name.GetCString();
463        }
464
465        void
466        SetUserNameNotFound (uint32_t uid)
467        {
468            Mutex::Locker locker (m_uid_map_mutex);
469            m_uid_map[uid] = ConstString();
470        }
471
472
473        void
474        ClearCachedUserNames ()
475        {
476            Mutex::Locker locker (m_uid_map_mutex);
477            m_uid_map.clear();
478        }
479
480        const char *
481        GetCachedGroupName (uint32_t gid)
482        {
483            Mutex::Locker locker (m_gid_map_mutex);
484            IDToNameMap::iterator pos = m_gid_map.find (gid);
485            if (pos != m_gid_map.end())
486            {
487                // return the empty string if our string is NULL
488                // so we can tell when things were in the negative
489                // cached (didn't find a valid group name, don't keep
490                // trying)
491                return pos->second.AsCString("");
492            }
493            return NULL;
494        }
495
496        const char *
497        SetCachedGroupName (uint32_t gid, const char *name, size_t name_len)
498        {
499            Mutex::Locker locker (m_gid_map_mutex);
500            ConstString const_name (name);
501            m_gid_map[gid] = const_name;
502            if (m_max_gid_name_len < name_len)
503                m_max_gid_name_len = name_len;
504            // Const strings lives forever in our const string pool, so we can return the const char *
505            return const_name.GetCString();
506        }
507
508        void
509        SetGroupNameNotFound (uint32_t gid)
510        {
511            Mutex::Locker locker (m_gid_map_mutex);
512            m_gid_map[gid] = ConstString();
513        }
514
515        void
516        ClearCachedGroupNames ()
517        {
518            Mutex::Locker locker (m_gid_map_mutex);
519            m_gid_map.clear();
520        }
521
522    private:
523        DISALLOW_COPY_AND_ASSIGN (Platform);
524    };
525
526
527    class PlatformList
528    {
529    public:
530        PlatformList() :
531            m_mutex (Mutex::eMutexTypeRecursive),
532            m_platforms (),
533            m_selected_platform_sp()
534        {
535        }
536
537        ~PlatformList()
538        {
539        }
540
541        void
542        Append (const lldb::PlatformSP &platform_sp, bool set_selected)
543        {
544            Mutex::Locker locker (m_mutex);
545            m_platforms.push_back (platform_sp);
546            if (set_selected)
547                m_selected_platform_sp = m_platforms.back();
548        }
549
550        size_t
551        GetSize()
552        {
553            Mutex::Locker locker (m_mutex);
554            return m_platforms.size();
555        }
556
557        lldb::PlatformSP
558        GetAtIndex (uint32_t idx)
559        {
560            lldb::PlatformSP platform_sp;
561            {
562                Mutex::Locker locker (m_mutex);
563                if (idx < m_platforms.size())
564                    platform_sp = m_platforms[idx];
565            }
566            return platform_sp;
567        }
568
569        //------------------------------------------------------------------
570        /// Select the active platform.
571        ///
572        /// In order to debug remotely, other platform's can be remotely
573        /// connected to and set as the selected platform for any subsequent
574        /// debugging. This allows connection to remote targets and allows
575        /// the ability to discover process info, launch and attach to remote
576        /// processes.
577        //------------------------------------------------------------------
578        lldb::PlatformSP
579        GetSelectedPlatform ()
580        {
581            Mutex::Locker locker (m_mutex);
582            if (!m_selected_platform_sp && !m_platforms.empty())
583                m_selected_platform_sp = m_platforms.front();
584
585            return m_selected_platform_sp;
586        }
587
588        void
589        SetSelectedPlatform (const lldb::PlatformSP &platform_sp)
590        {
591            if (platform_sp)
592            {
593                Mutex::Locker locker (m_mutex);
594                const size_t num_platforms = m_platforms.size();
595                for (size_t idx=0; idx<num_platforms; ++idx)
596                {
597                    if (m_platforms[idx].get() == platform_sp.get())
598                    {
599                        m_selected_platform_sp = m_platforms[idx];
600                        return;
601                    }
602                }
603                m_platforms.push_back (platform_sp);
604                m_selected_platform_sp = m_platforms.back();
605            }
606        }
607
608    protected:
609        typedef std::vector<lldb::PlatformSP> collection;
610        mutable Mutex m_mutex;
611        collection m_platforms;
612        lldb::PlatformSP m_selected_platform_sp;
613
614    private:
615        DISALLOW_COPY_AND_ASSIGN (PlatformList);
616    };
617} // namespace lldb_private
618
619#endif  // liblldb_Platform_h_
620