1 //===-- StructuredDataPlugin.h ----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_TARGET_STRUCTUREDDATAPLUGIN_H
10 #define LLDB_TARGET_STRUCTUREDDATAPLUGIN_H
11 
12 #include "lldb/Core/PluginInterface.h"
13 #include "lldb/Utility/StructuredData.h"
14 
15 namespace lldb_private {
16 
17 class CommandObjectMultiword;
18 
19 /// Plugin that supports process-related structured data sent asynchronously
20 /// from the debug monitor (e.g. debugserver, lldb-server, etc.)
21 ///
22 /// This plugin type is activated by a Process-derived instance when that
23 /// instance detects that a given structured data feature is available.
24 ///
25 /// StructuredDataPlugin instances are inherently tied to a process.  The
26 /// main functionality they support is the ability to consume asynchronously-
27 /// delivered structured data from the process monitor, and do something
28 /// reasonable with it.  Something reasonable can include broadcasting a
29 /// StructuredData event, which other parts of the system can then do with
30 /// as they please.  An IDE could use this facility to retrieve CPU usage,
31 /// memory usage, and other run-time aspects of the process.  That data
32 /// can then be displayed meaningfully to the user through the IDE.
33 
34 /// For command-line LLDB, the Debugger instance listens for the structured
35 /// data events raised by the plugin, and give the plugin both the output
36 /// and error streams such that the plugin can display something about the
37 /// event, at a time when the debugger ensures it is safe to write to the
38 /// output or error streams.
39 
40 class StructuredDataPlugin
41     : public PluginInterface,
42       public std::enable_shared_from_this<StructuredDataPlugin> {
43 public:
44   ~StructuredDataPlugin() override;
45 
46   lldb::ProcessSP GetProcess() const;
47 
48   // Public instance API
49 
50   /// Return whether this plugin supports the given StructuredData feature.
51   ///
52   /// When Process is informed of a list of process-monitor-supported
53   /// structured data features, Process will go through the list of plugins,
54   /// one at a time, and have the first plugin that supports a given feature
55   /// be the plugin instantiated to handle that feature.  There is a 1-1
56   /// correspondence between a Process instance and a StructuredDataPlugin
57   /// mapped to that process.  A plugin can support handling multiple
58   /// features, and if that happens, there is a single plugin instance
59   /// created covering all of the mapped features for a given process.
60   ///
61   /// \param[in] type_name
62   ///     The name of the feature tag supported by a process.
63   ///     e.g. "darwin-log".
64   ///
65   /// \return
66   ///     true if the plugin supports the feature; otherwise, false.
67   virtual bool SupportsStructuredDataType(ConstString type_name) = 0;
68 
69   /// Handle the arrival of asynchronous structured data from the process.
70   ///
71   /// When asynchronous structured data arrives from the process monitor,
72   /// it is immediately delivered to the plugin mapped for that feature
73   /// if one exists.  The structured data that arrives from a process
74   /// monitor must be a dictionary, and it must have a string field named
75   /// "type" that must contain the StructuredData feature name set as the
76   /// value.  This is the manner in which the data is routed to the proper
77   /// plugin instance.
78   ///
79   /// \param[in] process
80   ///     The process instance that just received the structured data.
81   ///     This will always be the same process for a given instance of
82   ///     a plugin.
83   ///
84   /// \param[in] type_name
85   ///     The name of the feature tag for the asynchronous structured data.
86   ///     Note this data will also be present in the \b object_sp dictionary
87   ///     under the string value with key "type".
88   ///
89   /// \param[in] object_sp
90   ///     A shared pointer to the structured data that arrived.  This must
91   ///     be a dictionary.  The only key required is the aforementioned
92   ///     key named "type" that must be a string value containing the
93   ///     structured data type name.
94   virtual void
95   HandleArrivalOfStructuredData(Process &process, ConstString type_name,
96                                 const StructuredData::ObjectSP &object_sp) = 0;
97 
98   /// Get a human-readable description of the contents of the data.
99   ///
100   /// In command-line LLDB, this method will be called by the Debugger
101   /// instance for each structured data event generated, and the output
102   /// will be printed to the LLDB console.  If nothing is added to the stream,
103   /// nothing will be printed; otherwise, a newline will be added to the end
104   /// when displayed.
105   ///
106   /// \param[in] object_sp
107   ///     A shared pointer to the structured data to format.
108   ///
109   /// \param[in] stream
110   ///     The stream where the structured data should be pretty printed.
111   ///
112   /// \return
113   ///     The error if formatting the object contents failed; otherwise,
114   ///     success.
115   virtual Status GetDescription(const StructuredData::ObjectSP &object_sp,
116                                 lldb_private::Stream &stream) = 0;
117 
118   /// Returns whether the plugin's features are enabled.
119   ///
120   /// This is a convenience method for plugins that can enable or disable
121   /// their functionality.  It allows retrieval of this state without
122   /// requiring a cast.
123   ///
124   /// \param[in] type_name
125   ///     The name of the feature tag for the asynchronous structured data.
126   ///     This is needed for plugins that support more than one feature.
127   virtual bool GetEnabled(ConstString type_name) const;
128 
129   /// Allow the plugin to do work related to modules that loaded in the
130   /// the corresponding process.
131   ///
132   /// This method defaults to doing nothing.  Plugins can override it
133   /// if they have any behavior they want to enable/modify based on loaded
134   /// modules.
135   ///
136   /// \param[in] process
137   ///     The process that just was notified of modules having been loaded.
138   ///     This will always be the same process for a given instance of
139   ///     a plugin.
140   ///
141   /// \param[in] module_list
142   ///     The list of modules that the process registered as having just
143   ///     loaded.  See \b Process::ModulesDidLoad(...).
144   virtual void ModulesDidLoad(Process &process, ModuleList &module_list);
145 
146 protected:
147   // Derived-class API
148   StructuredDataPlugin(const lldb::ProcessWP &process_wp);
149 
150   /// Derived classes must call this before attempting to hook up commands
151   /// to the 'plugin structured-data' tree.
152   ///
153   /// This ensures the relevant command and options hook points for all
154   /// StructuredDataPlugin derived classes are available for this debugger.
155   /// If this has already happened, this call is a no-op.
156   ///
157   /// \param[in] debugger
158   ///     The Debugger instance for which we're creating the required shared
159   ///     components for the StructuredDataPlugin derived classes.
160   static void InitializeBasePluginForDebugger(Debugger &debugger);
161 
162 private:
163   lldb::ProcessWP m_process_wp;
164 
165   StructuredDataPlugin(const StructuredDataPlugin &) = delete;
166   const StructuredDataPlugin &operator=(const StructuredDataPlugin &) = delete;
167 };
168 }
169 
170 #endif
171