1 //===-- SystemRuntimeMacOSX.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_SystemRuntimeMacOSX_h_
11 #define liblldb_SystemRuntimeMacOSX_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <map>
16 #include <vector>
17 #include <string>
18 
19 // Other libraries and framework includes
20 
21 #include "lldb/Target/SystemRuntime.h"
22 #include "lldb/Core/ConstString.h"
23 #include "lldb/Core/ModuleList.h"
24 #include "lldb/Core/StructuredData.h"
25 #include "lldb/Core/UUID.h"
26 #include "lldb/Host/FileSpec.h"
27 #include "lldb/Host/Mutex.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/QueueItem.h"
30 
31 #include "AppleGetItemInfoHandler.h"
32 #include "AppleGetQueuesHandler.h"
33 #include "AppleGetPendingItemsHandler.h"
34 #include "AppleGetThreadItemInfoHandler.h"
35 
36 class SystemRuntimeMacOSX : public lldb_private::SystemRuntime
37 {
38 public:
39     //------------------------------------------------------------------
40     // Static Functions
41     //------------------------------------------------------------------
42     static void
43     Initialize();
44 
45     static void
46     Terminate();
47 
48     static lldb_private::ConstString
49     GetPluginNameStatic();
50 
51     static const char *
52     GetPluginDescriptionStatic();
53 
54     static lldb_private::SystemRuntime *
55     CreateInstance (lldb_private::Process *process);
56 
57 
58     //------------------------------------------------------------------
59     // instance methods
60     //------------------------------------------------------------------
61 
62     SystemRuntimeMacOSX (lldb_private::Process *process);
63 
64     virtual
65     ~SystemRuntimeMacOSX ();
66 
67     void
68     Clear (bool clear_process);
69 
70     void
71     Detach ();
72 
73     const std::vector<lldb_private::ConstString> &
74     GetExtendedBacktraceTypes ();
75 
76     lldb::ThreadSP
77     GetExtendedBacktraceThread (lldb::ThreadSP thread, lldb_private::ConstString type);
78 
79     lldb::ThreadSP
80     GetExtendedBacktraceForQueueItem (lldb::QueueItemSP queue_item_sp, lldb_private::ConstString type);
81 
82     lldb::ThreadSP
83     GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref);
84 
85     void
86     PopulateQueueList (lldb_private::QueueList &queue_list);
87 
88     void
89     PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count, lldb_private::QueueList &queue_list);
90 
91     void
92     PopulatePendingQueuesUsingLibBTR (lldb::addr_t items_buffer, uint64_t items_buffer_size, uint64_t count, lldb_private::Queue *queue);
93 
94     std::string
95     GetQueueNameFromThreadQAddress (lldb::addr_t dispatch_qaddr);
96 
97     lldb::queue_id_t
98     GetQueueIDFromThreadQAddress (lldb::addr_t dispatch_qaddr);
99 
100     lldb::addr_t
101     GetLibdispatchQueueAddressFromThreadQAddress (lldb::addr_t dispatch_qaddr);
102 
103     void
104     PopulatePendingItemsForQueue (lldb_private::Queue *queue);
105 
106     void
107     CompleteQueueItem (lldb_private::QueueItem *queue_item, lldb::addr_t item_ref);
108 
109     virtual lldb::QueueKind
110     GetQueueKind (lldb::addr_t dispatch_queue_addr);
111 
112     virtual void
113     AddThreadExtendedInfoPacketHints (lldb_private::StructuredData::ObjectSP dict);
114 
115     virtual bool
116     SafeToCallFunctionsOnThisThread (lldb::ThreadSP thread_sp);
117 
118     //------------------------------------------------------------------
119     // PluginInterface protocol
120     //------------------------------------------------------------------
121     virtual lldb_private::ConstString
122     GetPluginName();
123 
124     virtual uint32_t
125     GetPluginVersion();
126 
127 
128 protected:
129     lldb::user_id_t m_break_id;
130     mutable lldb_private::Mutex m_mutex;
131 
132 private:
133 
134     struct libBacktraceRecording_info {
135         uint16_t    queue_info_version;
136         uint16_t    queue_info_data_offset;
137         uint16_t    item_info_version;
138         uint16_t    item_info_data_offset;
139 
140         libBacktraceRecording_info () :
141             queue_info_version(0),
142             queue_info_data_offset(0),
143             item_info_version(0),
144             item_info_data_offset(0) {}
145     };
146 
147 
148     // A structure which reflects the data recorded in the
149     // libBacktraceRecording introspection_dispatch_item_info_s.
150     struct ItemInfo {
151         lldb::addr_t    item_that_enqueued_this;
152         lldb::addr_t    function_or_block;
153         uint64_t        enqueuing_thread_id;
154         uint64_t        enqueuing_queue_serialnum;
155         uint64_t        target_queue_serialnum;
156         uint32_t        enqueuing_callstack_frame_count;
157         uint32_t        stop_id;
158         std::vector<lldb::addr_t>   enqueuing_callstack;
159         std::string                 enqueuing_thread_label;
160         std::string                 enqueuing_queue_label;
161         std::string                 target_queue_label;
162     };
163 
164     // The offsets of different fields of the dispatch_queue_t structure in
165     // a thread/queue process.
166     // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s
167     // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot be cached.
168     // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value that can be cached.
169     struct LibdispatchOffsets
170     {
171         uint16_t dqo_version;
172         uint16_t dqo_label;
173         uint16_t dqo_label_size;
174         uint16_t dqo_flags;
175         uint16_t dqo_flags_size;
176         uint16_t dqo_serialnum;
177         uint16_t dqo_serialnum_size;
178         uint16_t dqo_width;
179         uint16_t dqo_width_size;
180         uint16_t dqo_running;
181         uint16_t dqo_running_size;
182 
183         uint16_t dqo_suspend_cnt;         // version 5 and later, starting with Mac OS X 10.10/iOS 8
184         uint16_t dqo_suspend_cnt_size;    // version 5 and later, starting with Mac OS X 10.10/iOS 8
185         uint16_t dqo_target_queue;        // version 5 and later, starting with Mac OS X 10.10/iOS 8
186         uint16_t dqo_target_queue_size;   // version 5 and later, starting with Mac OS X 10.10/iOS 8
187         uint16_t dqo_priority;            // version 5 and later, starting with Mac OS X 10.10/iOS 8
188         uint16_t dqo_priority_size;       // version 5 and later, starting with Mac OS X 10.10/iOS 8
189 
190         LibdispatchOffsets ()
191         {
192             dqo_version = UINT16_MAX;
193             dqo_flags  = UINT16_MAX;
194             dqo_serialnum = UINT16_MAX;
195             dqo_label = UINT16_MAX;
196             dqo_width = UINT16_MAX;
197             dqo_running = UINT16_MAX;
198             dqo_suspend_cnt = UINT16_MAX;
199             dqo_target_queue = UINT16_MAX;
200             dqo_target_queue = UINT16_MAX;
201             dqo_priority = UINT16_MAX;
202         };
203 
204         bool
205         IsValid ()
206         {
207             return dqo_version != UINT16_MAX;
208         }
209 
210         bool
211         LabelIsValid ()
212         {
213             return dqo_label != UINT16_MAX;
214         }
215     };
216 
217     struct LibdispatchVoucherOffsets
218     {
219         uint16_t vo_version;
220         uint16_t vo_activity_ids_count;
221         uint16_t vo_activity_ids_count_size;
222         uint16_t vo_activity_ids_array;
223         uint16_t vo_activity_ids_array_entry_size;
224 
225         LibdispatchVoucherOffsets () :
226             vo_version (UINT16_MAX),
227             vo_activity_ids_count (UINT16_MAX),
228             vo_activity_ids_count_size (UINT16_MAX),
229             vo_activity_ids_array (UINT16_MAX),
230             vo_activity_ids_array_entry_size (UINT16_MAX)
231         { }
232 
233         bool IsValid () { return vo_version != UINT16_MAX; }
234     };
235 
236     struct LibdispatchTSDIndexes
237     {
238         uint16_t dti_version;
239         uint64_t dti_queue_index;
240         uint64_t dti_voucher_index;
241         uint64_t dti_qos_class_index;
242 
243         LibdispatchTSDIndexes () :
244             dti_version (UINT16_MAX),
245             dti_queue_index (UINT64_MAX),
246             dti_voucher_index (UINT64_MAX),
247             dti_qos_class_index (UINT64_MAX)
248         { }
249 
250         bool IsValid () { return dti_version != UINT16_MAX; }
251     };
252 
253     struct LibpthreadOffsets
254     {
255         uint16_t    plo_version;
256         uint16_t    plo_pthread_tsd_base_offset;
257         uint16_t    plo_pthread_tsd_base_address_offset;
258         uint16_t    plo_pthread_tsd_entry_size;
259 
260         LibpthreadOffsets () :
261             plo_version (UINT16_MAX),
262             plo_pthread_tsd_base_offset (UINT16_MAX),
263             plo_pthread_tsd_base_address_offset (UINT16_MAX),
264             plo_pthread_tsd_entry_size (UINT16_MAX)
265         {
266         }
267 
268         bool IsValid ()
269         {
270             return plo_version != UINT16_MAX;
271         }
272     };
273 
274     // The libBacktraceRecording function __introspection_dispatch_queue_get_pending_items has
275     // two forms.  It can either return a simple array of item_refs (void *) size or it can return
276     // a header with uint32_t version, a uint32_t size of item, and then an array of item_refs (void*)
277     // and code addresses (void*) for all the pending blocks.
278 
279     struct ItemRefAndCodeAddress {
280         lldb::addr_t    item_ref;
281         lldb::addr_t    code_address;
282     };
283 
284     struct PendingItemsForQueue {
285         bool new_style;              // new-style means both item_refs and code_addresses avail
286                                      // old-style means only item_refs is filled in
287         std::vector<ItemRefAndCodeAddress> item_refs_and_code_addresses;
288     };
289 
290     bool
291     BacktraceRecordingHeadersInitialized ();
292 
293     void
294     ReadLibdispatchOffsetsAddress();
295 
296     void
297     ReadLibdispatchOffsets ();
298 
299     void
300     ReadLibpthreadOffsetsAddress();
301 
302     void
303     ReadLibpthreadOffsets ();
304 
305     void
306     ReadLibdispatchTSDIndexesAddress ();
307 
308     void
309     ReadLibdispatchTSDIndexes ();
310 
311     PendingItemsForQueue
312     GetPendingItemRefsForQueue (lldb::addr_t queue);
313 
314     ItemInfo
315     ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor);
316 
317     lldb_private::AppleGetQueuesHandler m_get_queues_handler;
318     lldb_private::AppleGetPendingItemsHandler m_get_pending_items_handler;
319     lldb_private::AppleGetItemInfoHandler m_get_item_info_handler;
320     lldb_private::AppleGetThreadItemInfoHandler m_get_thread_item_info_handler;
321 
322     lldb::addr_t                        m_page_to_free;
323     uint64_t                            m_page_to_free_size;
324     libBacktraceRecording_info          m_lib_backtrace_recording_info;
325 
326     lldb::addr_t                        m_dispatch_queue_offsets_addr;
327     struct LibdispatchOffsets           m_libdispatch_offsets;
328 
329     lldb::addr_t                        m_libpthread_layout_offsets_addr;
330     struct LibpthreadOffsets            m_libpthread_offsets;
331 
332     lldb::addr_t                        m_dispatch_tsd_indexes_addr;
333     struct LibdispatchTSDIndexes        m_libdispatch_tsd_indexes;
334 
335     lldb::addr_t                        m_dispatch_voucher_offsets_addr;
336     struct LibdispatchVoucherOffsets    m_libdispatch_voucher_offsets;
337 
338     DISALLOW_COPY_AND_ASSIGN (SystemRuntimeMacOSX);
339 };
340 
341 #endif  // liblldb_SystemRuntimeMacOSX_h_
342