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