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