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 #include "llvm/Support/MachO.h"
21 
22 #include "lldb/Target/SystemRuntime.h"
23 #include "lldb/Host/FileSpec.h"
24 #include "lldb/Core/ConstString.h"
25 #include "lldb/Core/ModuleList.h"
26 #include "lldb/Core/UUID.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     void
101     PopulatePendingItemsForQueue (lldb_private::Queue *queue);
102 
103     //------------------------------------------------------------------
104     // PluginInterface protocol
105     //------------------------------------------------------------------
106     virtual lldb_private::ConstString
107     GetPluginName();
108 
109     virtual uint32_t
110     GetPluginVersion();
111 
112 
113 protected:
114     lldb::user_id_t m_break_id;
115     mutable lldb_private::Mutex m_mutex;
116 
117 private:
118 
119     struct libBacktraceRecording_info {
120         uint16_t    queue_info_version;
121         uint16_t    queue_info_data_offset;
122         uint16_t    item_info_version;
123         uint16_t    item_info_data_offset;
124 
125         libBacktraceRecording_info () :
126             queue_info_version(0),
127             queue_info_data_offset(0),
128             item_info_version(0),
129             item_info_data_offset(0) {}
130     };
131 
132 
133     // A structure which reflects the data recorded in the
134     // libBacktraceRecording introspection_dispatch_item_info_s.
135     struct ItemInfo {
136         lldb::addr_t    item_that_enqueued_this;
137         lldb::addr_t    function_or_block;
138         uint64_t        enqueuing_thread_id;
139         uint64_t        enqueuing_queue_serialnum;
140         uint64_t        target_queue_serialnum;
141         uint32_t        enqueuing_callstack_frame_count;
142         uint32_t        stop_id;
143         std::vector<lldb::addr_t>   enqueuing_callstack;
144         std::string                 enqueuing_thread_label;
145         std::string                 enqueuing_queue_label;
146         std::string                 target_queue_label;
147     };
148 
149     // The offsets of different fields of the dispatch_queue_t structure in
150     // a thread/queue process.
151     // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s
152     // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot be cached.
153     // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value that can be cached.
154     struct LibdispatchOffsets
155     {
156         uint16_t dqo_version;
157         uint16_t dqo_label;
158         uint16_t dqo_label_size;
159         uint16_t dqo_flags;
160         uint16_t dqo_flags_size;
161         uint16_t dqo_serialnum;
162         uint16_t dqo_serialnum_size;
163         uint16_t dqo_width;
164         uint16_t dqo_width_size;
165         uint16_t dqo_running;
166         uint16_t dqo_running_size;
167 
168         LibdispatchOffsets ()
169         {
170             dqo_version = UINT16_MAX;
171             dqo_flags  = UINT16_MAX;
172             dqo_serialnum = UINT16_MAX;
173             dqo_label = UINT16_MAX;
174             dqo_width = UINT16_MAX;
175             dqo_running = UINT16_MAX;
176         };
177 
178         bool
179         IsValid ()
180         {
181             return dqo_version != UINT16_MAX;
182         }
183 
184         bool
185         LabelIsValid ()
186         {
187             return dqo_label != UINT16_MAX;
188         }
189     };
190 
191     bool
192     BacktraceRecordingHeadersInitialized ();
193 
194     void
195     ReadLibdispatchOffsetsAddress();
196 
197     void
198     ReadLibdispatchOffsets ();
199 
200     std::vector<lldb::addr_t>
201     GetPendingItemRefsForQueue (lldb::addr_t queue);
202 
203     ItemInfo
204     ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor);
205 
206     lldb_private::AppleGetQueuesHandler m_get_queues_handler;
207     lldb_private::AppleGetPendingItemsHandler m_get_pending_items_handler;
208     lldb_private::AppleGetItemInfoHandler m_get_item_info_handler;
209     lldb_private::AppleGetThreadItemInfoHandler m_get_thread_item_info_handler;
210 
211     lldb::addr_t                        m_page_to_free;
212     uint64_t                            m_page_to_free_size;
213     libBacktraceRecording_info          m_lib_backtrace_recording_info;
214     lldb::addr_t                        m_dispatch_queue_offsets_addr;
215     struct LibdispatchOffsets           m_libdispatch_offsets;
216 
217     DISALLOW_COPY_AND_ASSIGN (SystemRuntimeMacOSX);
218 };
219 
220 #endif  // liblldb_SystemRuntimeMacOSX_h_
221