xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/SystemRuntime.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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
GetExtendedBacktraceForQueueItem(lldb::QueueItemSP queue_item_sp,ConstString type)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.
PopulateQueueList(lldb_private::QueueList & queue_list)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
GetQueueNameFromThreadQAddress(lldb::addr_t dispatch_qaddr)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
GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr)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
GetLibdispatchQueueAddressFromThreadQAddress(lldb::addr_t dispatch_qaddr)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.
GetQueueKind(lldb::addr_t dispatch_qaddr)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.
PopulatePendingItemsForQueue(lldb_private::Queue * queue)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.
CompleteQueueItem(lldb_private::QueueItem * queue_item,lldb::addr_t item_ref)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.
AddThreadExtendedInfoPacketHints(lldb_private::StructuredData::ObjectSP dict)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.
SafeToCallFunctionsOnThisThread(lldb::ThreadSP thread_sp)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