1 | //===-- SystemRuntime.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_SYSTEMRUNTIME_H |
10 | #define LLDB_TARGET_SYSTEMRUNTIME_H |
11 | |
12 | #include <vector> |
13 | |
14 | #include "lldb/Core/ModuleList.h" |
15 | #include "lldb/Core/PluginInterface.h" |
16 | #include "lldb/Target/QueueItem.h" |
17 | #include "lldb/Target/QueueList.h" |
18 | #include "lldb/Target/Runtime.h" |
19 | #include "lldb/Utility/ConstString.h" |
20 | #include "lldb/Utility/StructuredData.h" |
21 | #include "lldb/lldb-private.h" |
22 | #include "lldb/lldb-public.h" |
23 | |
24 | namespace lldb_private { |
25 | |
26 | /// \class SystemRuntime SystemRuntime.h "lldb/Target/SystemRuntime.h" |
27 | /// A plug-in interface definition class for system runtimes. |
28 | /// |
29 | /// The system runtime plugins can collect information from the system |
30 | /// libraries during a Process' lifetime and provide information about how |
31 | /// objects/threads were originated. |
32 | /// |
33 | /// For instance, a system runtime plugin use a breakpoint when threads are |
34 | /// created to record the backtrace of where that thread was created. Later, |
35 | /// when backtracing the created thread, it could extend the backtrace to show |
36 | /// where it was originally created from. |
37 | /// |
38 | /// The plugin will insert its own breakpoint when Created and start |
39 | /// collecting information. Later when it comes time to augment a Thread, it |
40 | /// can be asked to provide that information. |
41 | /// |
42 | |
43 | class SystemRuntime : public Runtime, public PluginInterface { |
44 | public: |
45 | /// Find a system runtime plugin for a given process. |
46 | /// |
47 | /// Scans the installed SystemRuntime plugins and tries to find an instance |
48 | /// that can be used to track image changes in \a process. |
49 | /// |
50 | /// \param[in] process |
51 | /// The process for which to try and locate a system runtime |
52 | /// plugin instance. |
53 | static SystemRuntime *FindPlugin(Process *process); |
54 | |
55 | /// Construct with a process. |
56 | SystemRuntime(Process *process); |
57 | |
58 | /// Destructor. |
59 | /// |
60 | /// The destructor is virtual since this class is designed to be inherited |
61 | /// by the plug-in instance. |
62 | ~SystemRuntime() override; |
63 | |
64 | /// Called after attaching to a process. |
65 | /// |
66 | /// Allow the SystemRuntime plugin to execute some code after attaching to a |
67 | /// process. |
68 | virtual void DidAttach(); |
69 | |
70 | /// Called after launching a process. |
71 | /// |
72 | /// Allow the SystemRuntime plugin to execute some code after launching a |
73 | /// process. |
74 | virtual void DidLaunch(); |
75 | |
76 | /// Called when modules have been loaded in the process. |
77 | /// |
78 | /// Allow the SystemRuntime plugin to enable logging features in the system |
79 | /// runtime libraries. |
80 | void ModulesDidLoad(const ModuleList &module_list) override; |
81 | |
82 | /// Called before detaching from a process. |
83 | /// |
84 | /// This will give a SystemRuntime plugin a chance to free any resources in |
85 | /// the inferior process before we detach. |
86 | virtual void Detach(); |
87 | |
88 | /// Return a list of thread origin extended backtraces that may be |
89 | /// available. |
90 | /// |
91 | /// A System Runtime may be able to provide a backtrace of when this |
92 | /// thread was originally created. Furthermore, it may be able to provide |
93 | /// that extended backtrace for different styles of creation. On a system |
94 | /// with both pthreads and libdispatch, aka Grand Central Dispatch, queues, |
95 | /// the system runtime may be able to provide the pthread creation of the |
96 | /// thread and it may also be able to provide the backtrace of when this GCD |
97 | /// queue work block was enqueued. The caller may request these different |
98 | /// origins by name. |
99 | /// |
100 | /// The names will be provided in the order that they are most likely to be |
101 | /// requested. For instance, a most natural order may be to request the GCD |
102 | /// libdispatch queue origin. If there is none, then request the pthread |
103 | /// origin. |
104 | /// |
105 | /// \return |
106 | /// A vector of ConstStrings with names like "pthread" or "libdispatch". |
107 | /// An empty vector may be returned if no thread origin extended |
108 | /// backtrace capabilities are available. |
109 | virtual const std::vector<ConstString> &GetExtendedBacktraceTypes(); |
110 | |
111 | /// Return a Thread which shows the origin of this thread's creation. |
112 | /// |
113 | /// This likely returns a HistoryThread which shows how thread was |
114 | /// originally created (e.g. "pthread" type), or how the work that is |
115 | /// currently executing on it was originally enqueued (e.g. "libdispatch" |
116 | /// type). |
117 | /// |
118 | /// There may be a chain of thread-origins; it may be informative to the end |
119 | /// user to query the returned ThreadSP for its origins as well. |
120 | /// |
121 | /// \param [in] thread |
122 | /// The thread to examine. |
123 | /// |
124 | /// \param [in] type |
125 | /// The type of thread origin being requested. The types supported |
126 | /// are returned from SystemRuntime::GetExtendedBacktraceTypes. |
127 | /// |
128 | /// \return |
129 | /// A ThreadSP which will have a StackList of frames. This Thread will |
130 | /// not appear in the Process' list of current threads. Normal thread |
131 | /// operations like stepping will not be available. This is a historical |
132 | /// view thread and may be only useful for showing a backtrace. |
133 | /// |
134 | /// An empty ThreadSP will be returned if no thread origin is available. |
135 | virtual lldb::ThreadSP GetExtendedBacktraceThread(lldb::ThreadSP thread, |
136 | ConstString type); |
137 | |
138 | /// Get the extended backtrace thread for a QueueItem |
139 | /// |
140 | /// A QueueItem represents a function/block that will be executed on |
141 | /// a libdispatch queue in the future, or it represents a function/block |
142 | /// that is currently executing on a thread. |
143 | /// |
144 | /// This method will report a thread backtrace of the function that enqueued |
145 | /// it originally, if possible. |
146 | /// |
147 | /// \param [in] queue_item_sp |
148 | /// The QueueItem that we are getting an extended backtrace for. |
149 | /// |
150 | /// \param [in] type |
151 | /// The type of extended backtrace to fetch. The types supported |
152 | /// are returned from SystemRuntime::GetExtendedBacktraceTypes. |
153 | /// |
154 | /// \return |
155 | /// If an extended backtrace is available, it is returned. Else |
156 | /// an empty ThreadSP is returned. |
157 | virtual lldb::ThreadSP |
158 | GetExtendedBacktraceForQueueItem(lldb::QueueItemSP queue_item_sp, |
159 | ConstString type) { |
160 | return lldb::ThreadSP(); |
161 | } |
162 | |
163 | /// Populate the Process' QueueList with libdispatch / GCD queues that |
164 | /// exist. |
165 | /// |
166 | /// When process execution is paused, the SystemRuntime may be called to |
167 | /// fill in the list of Queues that currently exist. |
168 | /// |
169 | /// \param [out] queue_list |
170 | /// This QueueList will be cleared, and any queues that currently exist |
171 | /// will be added. An empty QueueList will be returned if no queues |
172 | /// exist or if this Systemruntime does not support libdispatch queues. |
173 | virtual void PopulateQueueList(lldb_private::QueueList &queue_list) {} |
174 | |
175 | /// Get the queue name for a thread given a thread's dispatch_qaddr. |
176 | /// |
177 | /// On systems using libdispatch queues, a thread may be associated with a |
178 | /// queue. There will be a call to get the thread's dispatch_qaddr. At the |
179 | /// dispatch_qaddr we will find the address of this thread's |
180 | /// dispatch_queue_t structure. Given the address of the dispatch_queue_t |
181 | /// structure for a thread, get the queue name and return it. |
182 | /// |
183 | /// \param [in] dispatch_qaddr |
184 | /// The address of the dispatch_qaddr pointer for this thread. |
185 | /// |
186 | /// \return |
187 | /// The string of this queue's name. An empty string is returned if the |
188 | /// name could not be found. |
189 | virtual std::string |
190 | GetQueueNameFromThreadQAddress(lldb::addr_t dispatch_qaddr) { |
191 | return "" ; |
192 | } |
193 | |
194 | /// Get the QueueID for the libdispatch queue given the thread's |
195 | /// dispatch_qaddr. |
196 | /// |
197 | /// On systems using libdispatch queues, a thread may be associated with a |
198 | /// queue. There will be a call to get the thread's dispatch_qaddr. At the |
199 | /// dispatch_qaddr we will find the address of this thread's |
200 | /// dispatch_queue_t structure. Given the address of the dispatch_queue_t |
201 | /// structure for a thread, get the queue ID and return it. |
202 | /// |
203 | /// \param [in] dispatch_qaddr |
204 | /// The address of the dispatch_qaddr pointer for this thread. |
205 | /// |
206 | /// \return |
207 | /// The queue ID, or if it could not be retrieved, LLDB_INVALID_QUEUE_ID. |
208 | virtual lldb::queue_id_t |
209 | GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) { |
210 | return LLDB_INVALID_QUEUE_ID; |
211 | } |
212 | |
213 | /// Get the libdispatch_queue_t address for the queue given the thread's |
214 | /// dispatch_qaddr. |
215 | /// |
216 | /// On systems using libdispatch queues, a thread may be associated with a |
217 | /// queue. There will be a call to get the thread's dispatch_qaddr. Given |
218 | /// the thread's dispatch_qaddr, find the libdispatch_queue_t address and |
219 | /// return it. |
220 | /// |
221 | /// \param [in] dispatch_qaddr |
222 | /// The address of the dispatch_qaddr pointer for this thread. |
223 | /// |
224 | /// \return |
225 | /// The libdispatch_queue_t address, or LLDB_INVALID_ADDRESS if |
226 | /// unavailable/not found. |
227 | virtual lldb::addr_t |
228 | GetLibdispatchQueueAddressFromThreadQAddress(lldb::addr_t dispatch_qaddr) { |
229 | return LLDB_INVALID_ADDRESS; |
230 | } |
231 | |
232 | /// Retrieve the Queue kind for the queue at a thread's dispatch_qaddr. |
233 | /// |
234 | /// Retrieve the Queue kind - either eQueueKindSerial or |
235 | /// eQueueKindConcurrent, indicating that this queue processes work items |
236 | /// serially or concurrently. |
237 | /// |
238 | /// \return |
239 | /// The Queue kind, if it could be read, else eQueueKindUnknown. |
240 | virtual lldb::QueueKind GetQueueKind(lldb::addr_t dispatch_qaddr) { |
241 | return lldb::eQueueKindUnknown; |
242 | } |
243 | |
244 | /// Get the pending work items for a libdispatch Queue |
245 | /// |
246 | /// If this system/process is using libdispatch and the runtime can do so, |
247 | /// retrieve the list of pending work items for the specified Queue and add |
248 | /// it to the Queue. |
249 | /// |
250 | /// \param [in] queue |
251 | /// The queue of interest. |
252 | virtual void PopulatePendingItemsForQueue(lldb_private::Queue *queue) {} |
253 | |
254 | /// Complete the fields in a QueueItem |
255 | /// |
256 | /// PopulatePendingItemsForQueue() may not fill in all of the QueueItem |
257 | /// details; when the remaining fields are needed, they will be fetched by |
258 | /// call this method. |
259 | /// |
260 | /// \param [in] queue_item |
261 | /// The QueueItem that we will be completing. |
262 | /// |
263 | /// \param [in] item_ref |
264 | /// The item_ref token that is needed to retrieve the rest of the |
265 | /// information about the QueueItem. |
266 | virtual void CompleteQueueItem(lldb_private::QueueItem *queue_item, |
267 | lldb::addr_t item_ref) {} |
268 | |
269 | /// Add key-value pairs to the StructuredData dictionary object with |
270 | /// information debugserver may need when constructing the |
271 | /// jThreadExtendedInfo packet. |
272 | /// |
273 | /// \param [out] dict |
274 | /// Dictionary to which key-value pairs should be added; they will |
275 | /// be sent to the remote gdb server stub as arguments in the |
276 | /// jThreadExtendedInfo request. |
277 | virtual void AddThreadExtendedInfoPacketHints( |
278 | lldb_private::StructuredData::ObjectSP dict) {} |
279 | |
280 | /// Determine whether it is safe to run an expression on a given thread |
281 | /// |
282 | /// If a system must not run functions on a thread in some particular state, |
283 | /// this method gives a way for it to flag that the expression should not be |
284 | /// run. |
285 | /// |
286 | /// \param [in] thread_sp |
287 | /// The thread we want to run the expression on. |
288 | /// |
289 | /// \return |
290 | /// True will be returned if there are no known problems with running an |
291 | /// expression on this thread. False means that the inferior function |
292 | /// call should not be made on this thread. |
293 | virtual bool SafeToCallFunctionsOnThisThread(lldb::ThreadSP thread_sp) { |
294 | return true; |
295 | } |
296 | |
297 | protected: |
298 | std::vector<ConstString> m_types; |
299 | |
300 | private: |
301 | SystemRuntime(const SystemRuntime &) = delete; |
302 | const SystemRuntime &operator=(const SystemRuntime &) = delete; |
303 | }; |
304 | |
305 | } // namespace lldb_private |
306 | |
307 | #endif // LLDB_TARGET_SYSTEMRUNTIME_H |
308 | |