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