reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
//===-- SystemRuntimeMacOSX.h -----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_SystemRuntimeMacOSX_h_
#define liblldb_SystemRuntimeMacOSX_h_

#include <mutex>
#include <string>
#include <vector>

// Other libraries and framework include
#include "lldb/Core/ModuleList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/QueueItem.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"

#include "AppleGetItemInfoHandler.h"
#include "AppleGetPendingItemsHandler.h"
#include "AppleGetQueuesHandler.h"
#include "AppleGetThreadItemInfoHandler.h"

class SystemRuntimeMacOSX : public lldb_private::SystemRuntime {
public:
  SystemRuntimeMacOSX(lldb_private::Process *process);

  ~SystemRuntimeMacOSX() override;

  // Static Functions
  static void Initialize();

  static void Terminate();

  static lldb_private::ConstString GetPluginNameStatic();

  static const char *GetPluginDescriptionStatic();

  static lldb_private::SystemRuntime *
  CreateInstance(lldb_private::Process *process);

  // instance methods

  void Clear(bool clear_process);

  void Detach() override;

  const std::vector<lldb_private::ConstString> &
  GetExtendedBacktraceTypes() override;

  lldb::ThreadSP
  GetExtendedBacktraceThread(lldb::ThreadSP thread,
                             lldb_private::ConstString type) override;

  lldb::ThreadSP
  GetExtendedBacktraceForQueueItem(lldb::QueueItemSP queue_item_sp,
                                   lldb_private::ConstString type) override;

  lldb::ThreadSP GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref);

  void PopulateQueueList(lldb_private::QueueList &queue_list) override;

  void PopulateQueuesUsingLibBTR(lldb::addr_t queues_buffer,
                                 uint64_t queues_buffer_size, uint64_t count,
                                 lldb_private::QueueList &queue_list);

  void PopulatePendingQueuesUsingLibBTR(lldb::addr_t items_buffer,
                                        uint64_t items_buffer_size,
                                        uint64_t count,
                                        lldb_private::Queue *queue);

  std::string
  GetQueueNameFromThreadQAddress(lldb::addr_t dispatch_qaddr) override;

  lldb::queue_id_t
  GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) override;

  lldb::addr_t GetLibdispatchQueueAddressFromThreadQAddress(
      lldb::addr_t dispatch_qaddr) override;

  void PopulatePendingItemsForQueue(lldb_private::Queue *queue) override;

  void CompleteQueueItem(lldb_private::QueueItem *queue_item,
                         lldb::addr_t item_ref) override;

  lldb::QueueKind GetQueueKind(lldb::addr_t dispatch_queue_addr) override;

  void AddThreadExtendedInfoPacketHints(
      lldb_private::StructuredData::ObjectSP dict) override;

  bool SafeToCallFunctionsOnThisThread(lldb::ThreadSP thread_sp) override;

  // PluginInterface protocol
  lldb_private::ConstString GetPluginName() override;

  uint32_t GetPluginVersion() override;

protected:
  lldb::user_id_t m_break_id;
  mutable std::recursive_mutex m_mutex;

private:
  struct libBacktraceRecording_info {
    uint16_t queue_info_version;
    uint16_t queue_info_data_offset;
    uint16_t item_info_version;
    uint16_t item_info_data_offset;

    libBacktraceRecording_info()
        : queue_info_version(0), queue_info_data_offset(0),
          item_info_version(0), item_info_data_offset(0) {}
  };

  // A structure which reflects the data recorded in the
  // libBacktraceRecording introspection_dispatch_item_info_s.
  struct ItemInfo {
    lldb::addr_t item_that_enqueued_this;
    lldb::addr_t function_or_block;
    uint64_t enqueuing_thread_id;
    uint64_t enqueuing_queue_serialnum;
    uint64_t target_queue_serialnum;
    uint32_t enqueuing_callstack_frame_count;
    uint32_t stop_id;
    std::vector<lldb::addr_t> enqueuing_callstack;
    std::string enqueuing_thread_label;
    std::string enqueuing_queue_label;
    std::string target_queue_label;
  };

  // The offsets of different fields of the dispatch_queue_t structure in
  // a thread/queue process.
  // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s
  // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot
  // be cached.
  // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value
  // that can be cached.
  struct LibdispatchOffsets {
    uint16_t dqo_version;
    uint16_t dqo_label;
    uint16_t dqo_label_size;
    uint16_t dqo_flags;
    uint16_t dqo_flags_size;
    uint16_t dqo_serialnum;
    uint16_t dqo_serialnum_size;
    uint16_t dqo_width;
    uint16_t dqo_width_size;
    uint16_t dqo_running;
    uint16_t dqo_running_size;

    uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X
                              // 10.10/iOS 8
    uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS
                                   // X 10.10/iOS 8
    uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X
                               // 10.10/iOS 8
    uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS
                                    // X 10.10/iOS 8
    uint16_t
        dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8
    uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X
                                // 10.10/iOS 8

    LibdispatchOffsets() {
      dqo_version = UINT16_MAX;
      dqo_flags = UINT16_MAX;
      dqo_serialnum = UINT16_MAX;
      dqo_label = UINT16_MAX;
      dqo_width = UINT16_MAX;
      dqo_running = UINT16_MAX;
      dqo_suspend_cnt = UINT16_MAX;
      dqo_target_queue = UINT16_MAX;
      dqo_target_queue = UINT16_MAX;
      dqo_priority = UINT16_MAX;
    }

    bool IsValid() { return dqo_version != UINT16_MAX; }

    bool LabelIsValid() { return dqo_label != UINT16_MAX; }
  };

  struct LibdispatchVoucherOffsets {
    uint16_t vo_version;
    uint16_t vo_activity_ids_count;
    uint16_t vo_activity_ids_count_size;
    uint16_t vo_activity_ids_array;
    uint16_t vo_activity_ids_array_entry_size;

    LibdispatchVoucherOffsets()
        : vo_version(UINT16_MAX), vo_activity_ids_count(UINT16_MAX),
          vo_activity_ids_count_size(UINT16_MAX),
          vo_activity_ids_array(UINT16_MAX),
          vo_activity_ids_array_entry_size(UINT16_MAX) {}

    bool IsValid() { return vo_version != UINT16_MAX; }
  };

  struct LibdispatchTSDIndexes {
    uint16_t dti_version;
    uint64_t dti_queue_index;
    uint64_t dti_voucher_index;
    uint64_t dti_qos_class_index;

    LibdispatchTSDIndexes()
        : dti_version(UINT16_MAX), dti_queue_index(UINT64_MAX),
          dti_voucher_index(UINT64_MAX), dti_qos_class_index(UINT64_MAX) {}

    bool IsValid() { return dti_version != UINT16_MAX; }
  };

  struct LibpthreadOffsets {
    uint16_t plo_version;
    uint16_t plo_pthread_tsd_base_offset;
    uint16_t plo_pthread_tsd_base_address_offset;
    uint16_t plo_pthread_tsd_entry_size;

    LibpthreadOffsets()
        : plo_version(UINT16_MAX), plo_pthread_tsd_base_offset(UINT16_MAX),
          plo_pthread_tsd_base_address_offset(UINT16_MAX),
          plo_pthread_tsd_entry_size(UINT16_MAX) {}

    bool IsValid() { return plo_version != UINT16_MAX; }
  };

  // The libBacktraceRecording function
  // __introspection_dispatch_queue_get_pending_items has
  // two forms.  It can either return a simple array of item_refs (void *) size
  // or it can return
  // a header with uint32_t version, a uint32_t size of item, and then an array
  // of item_refs (void*)
  // and code addresses (void*) for all the pending blocks.

  struct ItemRefAndCodeAddress {
    lldb::addr_t item_ref;
    lldb::addr_t code_address;
  };

  struct PendingItemsForQueue {
    bool new_style; // new-style means both item_refs and code_addresses avail
                    // old-style means only item_refs is filled in
    std::vector<ItemRefAndCodeAddress> item_refs_and_code_addresses;
  };

  bool BacktraceRecordingHeadersInitialized();

  void ReadLibdispatchOffsetsAddress();

  void ReadLibdispatchOffsets();

  void ReadLibpthreadOffsetsAddress();

  void ReadLibpthreadOffsets();

  void ReadLibdispatchTSDIndexesAddress();

  void ReadLibdispatchTSDIndexes();

  PendingItemsForQueue GetPendingItemRefsForQueue(lldb::addr_t queue);

  ItemInfo ExtractItemInfoFromBuffer(lldb_private::DataExtractor &extractor);

  lldb_private::AppleGetQueuesHandler m_get_queues_handler;
  lldb_private::AppleGetPendingItemsHandler m_get_pending_items_handler;
  lldb_private::AppleGetItemInfoHandler m_get_item_info_handler;
  lldb_private::AppleGetThreadItemInfoHandler m_get_thread_item_info_handler;

  lldb::addr_t m_page_to_free;
  uint64_t m_page_to_free_size;
  libBacktraceRecording_info m_lib_backtrace_recording_info;

  lldb::addr_t m_dispatch_queue_offsets_addr;
  struct LibdispatchOffsets m_libdispatch_offsets;

  lldb::addr_t m_libpthread_layout_offsets_addr;
  struct LibpthreadOffsets m_libpthread_offsets;

  lldb::addr_t m_dispatch_tsd_indexes_addr;
  struct LibdispatchTSDIndexes m_libdispatch_tsd_indexes;

  lldb::addr_t m_dispatch_voucher_offsets_addr;
  struct LibdispatchVoucherOffsets m_libdispatch_voucher_offsets;

  DISALLOW_COPY_AND_ASSIGN(SystemRuntimeMacOSX);
};

#endif // liblldb_SystemRuntimeMacOSX_h_