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