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