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(llvm::StringRef 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, llvm::StringRef 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(llvm::StringRef 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 | |