Platform.h revision cb8977d726be451df9978a74088435667fa37da2
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 <string>
16#include <vector>
17
18// Other libraries and framework includes
19// Project includes
20#include "lldb/lldb-include.h"
21#include "lldb/Core/ArchSpec.h"
22#include "lldb/Core/PluginInterface.h"
23#include "lldb/Host/Mutex.h"
24
25namespace lldb_private {
26
27    //----------------------------------------------------------------------
28    /// @class Platform Platform.h "lldb/Target/Platform.h"
29    /// @brief A plug-in interface definition class for debug platform that
30    /// includes many platform abilities such as:
31    ///     @li getting platform information such as supported architectures,
32    ///         supported binary file formats and more
33    ///     @li launching new processes
34    ///     @li attaching to existing processes
35    ///     @li download/upload files
36    ///     @li execute shell commands
37    ///     @li listing and getting info for existing processes
38    ///     @li attaching and possibly debugging the platform's kernel
39    //----------------------------------------------------------------------
40    class Platform : public PluginInterface
41    {
42    public:
43
44        //------------------------------------------------------------------
45        /// Get the native host platform plug-in.
46        ///
47        /// There should only be one of these for each host that LLDB runs
48        /// upon that should be statically compiled in and registered using
49        /// preprocessor macros or other similar build mechanisms in a
50        /// PlatformSubclass::Initialize() function.
51        ///
52        /// This platform will be used as the default platform when launching
53        /// or attaching to processes unless another platform is specified.
54        //------------------------------------------------------------------
55        static lldb::PlatformSP
56        GetDefaultPlatform ();
57
58        static void
59        SetDefaultPlatform (const lldb::PlatformSP &platform_sp);
60
61        static lldb::PlatformSP
62        Create (const char *platform_name, Error &error);
63
64        static uint32_t
65        GetNumConnectedRemotePlatforms ();
66
67        static lldb::PlatformSP
68        GetConnectedRemotePlatformAtIndex (uint32_t idx);
69
70        //------------------------------------------------------------------
71        /// Default Constructor
72        //------------------------------------------------------------------
73        Platform (bool is_host_platform);
74
75        //------------------------------------------------------------------
76        /// Destructor.
77        ///
78        /// The destructor is virtual since this class is designed to be
79        /// inherited from by the plug-in instance.
80        //------------------------------------------------------------------
81        virtual
82        ~Platform();
83
84        //------------------------------------------------------------------
85        /// Set the target's executable based off of the existing
86        /// architecture information in \a target given a path to an
87        /// executable \a exe_file.
88        ///
89        /// Each platform knows the architectures that it supports and can
90        /// select the correct architecture slice within \a exe_file by
91        /// inspecting the architecture in \a target. If the target had an
92        /// architecture specified, then in can try and obey that request
93        /// and optionally fail if the architecture doesn't match up.
94        /// If no architecture is specified, the platform should select the
95        /// default architecture from \a exe_file. Any application bundles
96        /// or executable wrappers can also be inspected for the actual
97        /// application binary within the bundle that should be used.
98        ///
99        /// @return
100        ///     Returns \b true if this Platform plug-in was able to find
101        ///     a suitable executable, \b false otherwise.
102        //------------------------------------------------------------------
103        virtual Error
104        ResolveExecutable (const FileSpec &exe_file,
105                           const ArchSpec &arch,
106                           lldb::ModuleSP &module_sp);
107
108        bool
109        GetOSVersion (uint32_t &major,
110                      uint32_t &minor,
111                      uint32_t &update);
112
113        bool
114        SetOSVersion (uint32_t major,
115                      uint32_t minor,
116                      uint32_t update);
117
118        const char *
119        GetInstanceName ()
120        {
121            if (IsHost())
122                return "localhost";
123
124            if (IsConnected())
125            {
126                if (m_remote_instance_name.empty())
127                    GetRemoteInstanceName ();
128
129                if (!m_remote_instance_name.empty())
130                    return m_remote_instance_name.c_str();
131            }
132            return "remote";
133        }
134
135        virtual const char *
136        GetDescription () = 0;
137
138        //------------------------------------------------------------------
139        /// Report the current status for this platform.
140        ///
141        /// The returned string usually involves returning the OS version
142        /// (if available), and any SDK directory that might be being used
143        /// for local file caching, and if connected a quick blurb about
144        /// what this platform is connected to.
145        //------------------------------------------------------------------
146        virtual void
147        GetStatus (Stream &strm) = 0;
148
149        //------------------------------------------------------------------
150        // Subclasses must be able to fetch the current OS version
151        //
152        // Remote classes must be connected for this to succeed. Local
153        // subclasses don't need to override this function as it will just
154        // call the Host::GetOSVersion().
155        //------------------------------------------------------------------
156protected:
157        virtual bool
158        FetchRemoteOSVersion ()
159        {
160            return false;
161        }
162
163        //------------------------------------------------------------------
164        /// Locate a file for a platform.
165        ///
166        /// The default implementation of this function will return the same
167        /// file patch in \a local_file as was in \a platform_file.
168        ///
169        /// @param[in] platform_file
170        ///     The platform file path to locate and cache locally.
171        ///
172        /// @param[out] local_file
173        ///     A locally cached version of the platform file. For platforms
174        ///     that describe the current host computer, this will just be
175        ///     the same file. For remote platforms, this file might come from
176        ///     and SDK directory, or might need to be sync'ed over to the
177        ///     current machine for efficient debugging access.
178        ///
179        /// @return
180        ///     An error object.
181        //------------------------------------------------------------------
182public:
183        virtual Error
184        GetFile (const FileSpec &platform_file,
185                 const UUID *uuid_ptr,
186                 FileSpec &local_file);
187
188        virtual Error
189        ConnectRemote (Args& args);
190
191        virtual Error
192        DisconnectRemote ();
193
194        // Remote subclasses should override this and return a valid instance
195        // name if connected.
196        virtual const char *
197        GetRemoteInstanceName ()
198        {
199            return NULL;
200        }
201
202
203        //------------------------------------------------------------------
204        /// Get the platform's supported architectures in the order in which
205        /// they should be searched.
206        ///
207        /// @param[in] idx
208        ///     A zero based architecture index
209        ///
210        /// @param[out] arch
211        ///     A copy of the archgitecture at index if the return value is
212        ///     \b true.
213        ///
214        /// @return
215        ///     \b true if \a arch was filled in and is valid, \b false
216        ///     otherwise.
217        //------------------------------------------------------------------
218        virtual bool
219        GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) = 0;
220
221        virtual size_t
222        GetSoftwareBreakpointTrapOpcode (Target &target,
223                                         BreakpointSite *bp_site) = 0;
224
225        //------------------------------------------------------------------
226        /// Launch a new process.
227        ///
228        /// Launch a new process by spawning a new process using the
229        /// target object's executable module's file as the file to launch.
230        /// Arguments are given in \a argv, and the environment variables
231        /// are in \a envp. Standard input and output files can be
232        /// optionally re-directed to \a stdin_path, \a stdout_path, and
233        /// \a stderr_path.
234        ///
235        /// This function is not meant to be overridden by Process
236        /// subclasses. It will first call Process::WillLaunch (Module *)
237        /// and if that returns \b true, Process::DoLaunch (Module*,
238        /// char const *[],char const *[],const char *,const char *,
239        /// const char *) will be called to actually do the launching. If
240        /// DoLaunch returns \b true, then Process::DidLaunch() will be
241        /// called.
242        ///
243        /// @param[in] argv
244        ///     The argument array.
245        ///
246        /// @param[in] envp
247        ///     The environment array.
248        ///
249        /// @param[in] launch_flags
250        ///     Flags to modify the launch (@see lldb::LaunchFlags)
251        ///
252        /// @param[in] stdin_path
253        ///     The path to use when re-directing the STDIN of the new
254        ///     process. If all stdXX_path arguments are NULL, a pseudo
255        ///     terminal will be used.
256        ///
257        /// @param[in] stdout_path
258        ///     The path to use when re-directing the STDOUT of the new
259        ///     process. If all stdXX_path arguments are NULL, a pseudo
260        ///     terminal will be used.
261        ///
262        /// @param[in] stderr_path
263        ///     The path to use when re-directing the STDERR of the new
264        ///     process. If all stdXX_path arguments are NULL, a pseudo
265        ///     terminal will be used.
266        ///
267        /// @param[in] working_directory
268        ///     The working directory to have the child process run in
269        ///
270        /// @return
271        ///     An error object. Call GetID() to get the process ID if
272        ///     the error object is success.
273        //------------------------------------------------------------------
274//        virtual lldb::ProcessSP
275//        Launch (char const *argv[],
276//                char const *envp[],
277//                uint32_t launch_flags,
278//                const char *stdin_path,
279//                const char *stdout_path,
280//                const char *stderr_path,
281//                const char *working_directory,
282//                Error &error) = 0;
283
284        //------------------------------------------------------------------
285        /// Attach to an existing process using a process ID.
286        ///
287        /// This function is not meant to be overridden by Process
288        /// subclasses. It will first call Process::WillAttach (lldb::pid_t)
289        /// and if that returns \b true, Process::DoAttach (lldb::pid_t) will
290        /// be called to actually do the attach. If DoAttach returns \b
291        /// true, then Process::DidAttach() will be called.
292        ///
293        /// @param[in] pid
294        ///     The process ID that we should attempt to attach to.
295        ///
296        /// @return
297        ///     Returns \a pid if attaching was successful, or
298        ///     LLDB_INVALID_PROCESS_ID if attaching fails.
299        //------------------------------------------------------------------
300//        virtual lldb::ProcessSP
301//        Attach (lldb::pid_t pid,
302//                Error &error) = 0;
303
304        //------------------------------------------------------------------
305        /// Attach to an existing process by process name.
306        ///
307        /// This function is not meant to be overridden by Process
308        /// subclasses. It will first call
309        /// Process::WillAttach (const char *) and if that returns \b
310        /// true, Process::DoAttach (const char *) will be called to
311        /// actually do the attach. If DoAttach returns \b true, then
312        /// Process::DidAttach() will be called.
313        ///
314        /// @param[in] process_name
315        ///     A process name to match against the current process list.
316        ///
317        /// @return
318        ///     Returns \a pid if attaching was successful, or
319        ///     LLDB_INVALID_PROCESS_ID if attaching fails.
320        //------------------------------------------------------------------
321//        virtual lldb::ProcessSP
322//        Attach (const char *process_name,
323//                bool wait_for_launch,
324//                Error &error) = 0;
325
326        virtual uint32_t
327        FindProcessesByName (const char *name,
328                             lldb::NameMatchType name_match_type,
329                             ProcessInfoList &proc_infos) = 0;
330
331        virtual bool
332        GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info) = 0;
333
334        const std::string &
335        GetRemoteURL () const
336        {
337            return m_remote_url;
338        }
339
340        bool
341        IsHost () const
342        {
343            return m_is_host;    // Is this the default host platform?
344        }
345
346        bool
347        IsRemote () const
348        {
349            return !m_is_host;
350        }
351
352        bool
353        IsConnected () const
354        {
355            return m_is_connected;
356        }
357
358        const ArchSpec &
359        GetSystemArchitecture();
360
361        void
362        SetSystemArchitecture (const ArchSpec &arch)
363        {
364            m_system_arch = arch;
365            if (IsHost())
366                m_os_version_set_while_connected = m_system_arch.IsValid();
367        }
368
369        // Remote Platform subclasses need to override this function
370        virtual ArchSpec
371        FetchRemoteSystemArchitecture ()
372        {
373            return ArchSpec(); // Return an invalid architecture
374        }
375
376    protected:
377        bool m_is_host;
378        bool m_is_connected;
379        // Set to true when we are able to actually set the OS version while
380        // being connected. For remote platforms, we might set the version ahead
381        // of time before we actually connect and this version might change when
382        // we actually connect to a remote platform. For the host platform this
383        // will be set to the once we call Host::GetOSVersion().
384        bool m_os_version_set_while_connected;
385        bool m_system_arch_set_while_connected;
386        std::string m_remote_url;
387        std::string m_remote_instance_name;
388        uint32_t m_major_os_version;
389        uint32_t m_minor_os_version;
390        uint32_t m_update_os_version;
391        ArchSpec m_system_arch; // The architecture of the kernel or the remote platform
392    private:
393        DISALLOW_COPY_AND_ASSIGN (Platform);
394    };
395
396
397    class PlatformList
398    {
399    public:
400        PlatformList() :
401            m_mutex (Mutex::eMutexTypeRecursive),
402            m_platforms ()
403        {
404        }
405
406        ~PlatformList()
407        {
408        }
409
410        void
411        Append (const lldb::PlatformSP &platform_sp, bool set_selected)
412        {
413            Mutex::Locker locker (m_mutex);
414            m_platforms.push_back (platform_sp);
415            if (set_selected)
416                m_selected_platform_sp = m_platforms.back();
417        }
418
419        size_t
420        GetSize()
421        {
422            Mutex::Locker locker (m_mutex);
423            return m_platforms.size();
424        }
425
426        lldb::PlatformSP
427        GetAtIndex (uint32_t idx)
428        {
429            lldb::PlatformSP platform_sp;
430            {
431                Mutex::Locker locker (m_mutex);
432                if (idx < m_platforms.size())
433                    platform_sp = m_platforms[idx];
434            }
435            return platform_sp;
436        }
437
438        //------------------------------------------------------------------
439        /// Select the active platform.
440        ///
441        /// In order to debug remotely, other platform's can be remotely
442        /// connected to and set as the selected platform for any subsequent
443        /// debugging. This allows connection to remote targets and allows
444        /// the ability to discover process info, launch and attach to remote
445        /// processes.
446        //------------------------------------------------------------------
447        lldb::PlatformSP
448        GetSelectedPlatform ()
449        {
450            Mutex::Locker locker (m_mutex);
451            if (!m_selected_platform_sp && !m_platforms.empty())
452                m_selected_platform_sp = m_platforms.front();
453
454            return m_selected_platform_sp;
455        }
456
457        void
458        SetSelectedPlatform (const lldb::PlatformSP &platform_sp)
459        {
460            if (platform_sp)
461            {
462                Mutex::Locker locker (m_mutex);
463                const size_t num_platforms = m_platforms.size();
464                for (size_t idx=0; idx<num_platforms; ++idx)
465                {
466                    if (m_platforms[idx].get() == platform_sp.get())
467                    {
468                        m_selected_platform_sp = m_platforms[idx];
469                        return;
470                    }
471                }
472                m_platforms.push_back (platform_sp);
473                m_selected_platform_sp = m_platforms.back();
474            }
475        }
476
477    protected:
478        typedef std::vector<lldb::PlatformSP> collection;
479        mutable Mutex m_mutex;
480        collection m_platforms;
481        lldb::PlatformSP m_selected_platform_sp;
482
483    private:
484        DISALLOW_COPY_AND_ASSIGN (PlatformList);
485    };
486} // namespace lldb_private
487
488#endif  // liblldb_Platform_h_
489