Coverage Report

Created: 2022-01-22 13:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- SystemRuntimeMacOSX.cpp -------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "Plugins/Process/Utility/HistoryThread.h"
10
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
11
#include "lldb/Breakpoint/StoppointCallbackContext.h"
12
#include "lldb/Core/Module.h"
13
#include "lldb/Core/ModuleSpec.h"
14
#include "lldb/Core/PluginManager.h"
15
#include "lldb/Core/Section.h"
16
#include "lldb/Symbol/ObjectFile.h"
17
#include "lldb/Symbol/SymbolContext.h"
18
#include "lldb/Target/Process.h"
19
#include "lldb/Target/ProcessStructReader.h"
20
#include "lldb/Target/Queue.h"
21
#include "lldb/Target/QueueList.h"
22
#include "lldb/Target/Target.h"
23
#include "lldb/Target/Thread.h"
24
#include "lldb/Utility/DataBufferHeap.h"
25
#include "lldb/Utility/DataExtractor.h"
26
#include "lldb/Utility/FileSpec.h"
27
#include "lldb/Utility/Log.h"
28
#include "lldb/Utility/StreamString.h"
29
30
#include "SystemRuntimeMacOSX.h"
31
32
#include <memory>
33
34
using namespace lldb;
35
using namespace lldb_private;
36
37
LLDB_PLUGIN_DEFINE(SystemRuntimeMacOSX)
38
39
// Create an instance of this class. This function is filled into the plugin
40
// info class that gets handed out by the plugin factory and allows the lldb to
41
// instantiate an instance of this class.
42
2.79k
SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {
43
2.79k
  bool create = false;
44
2.79k
  if (!create) {
45
2.79k
    create = true;
46
2.79k
    Module *exe_module = process->GetTarget().GetExecutableModulePointer();
47
2.79k
    if (exe_module) {
48
2.71k
      ObjectFile *object_file = exe_module->GetObjectFile();
49
2.71k
      if (object_file) {
50
2.71k
        create = (object_file->GetStrata() == ObjectFile::eStrataUser);
51
2.71k
      }
52
2.71k
    }
53
54
2.79k
    if (create) {
55
2.78k
      const llvm::Triple &triple_ref =
56
2.78k
          process->GetTarget().GetArchitecture().GetTriple();
57
2.78k
      switch (triple_ref.getOS()) {
58
0
      case llvm::Triple::Darwin:
59
2.60k
      case llvm::Triple::MacOSX:
60
2.60k
      case llvm::Triple::IOS:
61
2.60k
      case llvm::Triple::TvOS:
62
2.60k
      case llvm::Triple::WatchOS:
63
      // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
64
2.60k
        create = triple_ref.getVendor() == llvm::Triple::Apple;
65
2.60k
        break;
66
181
      default:
67
181
        create = false;
68
181
        break;
69
2.78k
      }
70
2.78k
    }
71
2.79k
  }
72
73
2.79k
  if (create)
74
2.60k
    return new SystemRuntimeMacOSX(process);
75
184
  return nullptr;
76
2.79k
}
77
78
// Constructor
79
SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process)
80
    : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
81
      m_get_queues_handler(process), m_get_pending_items_handler(process),
82
      m_get_item_info_handler(process), m_get_thread_item_info_handler(process),
83
      m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0),
84
      m_lib_backtrace_recording_info(),
85
      m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS),
86
      m_libdispatch_offsets(),
87
      m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS),
88
      m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS),
89
      m_libdispatch_tsd_indexes(),
90
      m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS),
91
2.60k
      m_libdispatch_voucher_offsets() {}
92
93
// Destructor
94
2.60k
SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); }
95
96
0
void SystemRuntimeMacOSX::Detach() {
97
0
  m_get_queues_handler.Detach();
98
0
  m_get_pending_items_handler.Detach();
99
0
  m_get_item_info_handler.Detach();
100
0
  m_get_thread_item_info_handler.Detach();
101
0
}
102
103
// Clear out the state of this class.
104
2.60k
void SystemRuntimeMacOSX::Clear(bool clear_process) {
105
2.60k
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
106
107
2.60k
  if (m_process->IsAlive() && 
LLDB_BREAK_ID_IS_VALID10
(m_break_id))
108
0
    m_process->ClearBreakpointSiteByID(m_break_id);
109
110
2.60k
  if (clear_process)
111
2.60k
    m_process = nullptr;
112
2.60k
  m_break_id = LLDB_INVALID_BREAK_ID;
113
2.60k
}
114
115
std::string
116
2
SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) {
117
2
  std::string dispatch_queue_name;
118
2
  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
119
0
    return "";
120
121
2
  ReadLibdispatchOffsets();
122
2
  if (m_libdispatch_offsets.IsValid()) {
123
    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
124
    // thread - deref it to get the address of the dispatch_queue_t structure
125
    // for this thread's queue.
126
2
    Status error;
127
2
    addr_t dispatch_queue_addr =
128
2
        m_process->ReadPointerFromMemory(dispatch_qaddr, error);
129
2
    if (error.Success()) {
130
2
      if (m_libdispatch_offsets.dqo_version >= 4) {
131
        // libdispatch versions 4+, pointer to dispatch name is in the queue
132
        // structure.
133
2
        addr_t pointer_to_label_address =
134
2
            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
135
2
        addr_t label_addr =
136
2
            m_process->ReadPointerFromMemory(pointer_to_label_address, error);
137
2
        if (error.Success()) {
138
2
          m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name,
139
2
                                           error);
140
2
        }
141
2
      } else {
142
        // libdispatch versions 1-3, dispatch name is a fixed width char array
143
        // in the queue structure.
144
0
        addr_t label_addr =
145
0
            dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
146
0
        dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0');
147
0
        size_t bytes_read =
148
0
            m_process->ReadMemory(label_addr, &dispatch_queue_name[0],
149
0
                                  m_libdispatch_offsets.dqo_label_size, error);
150
0
        if (bytes_read < m_libdispatch_offsets.dqo_label_size)
151
0
          dispatch_queue_name.erase(bytes_read);
152
0
      }
153
2
    }
154
2
  }
155
2
  return dispatch_queue_name;
156
2
}
157
158
lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress(
159
0
    addr_t dispatch_qaddr) {
160
0
  addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
161
0
  Status error;
162
0
  libdispatch_queue_t_address =
163
0
      m_process->ReadPointerFromMemory(dispatch_qaddr, error);
164
0
  if (!error.Success()) {
165
0
    libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
166
0
  }
167
0
  return libdispatch_queue_t_address;
168
0
}
169
170
0
lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) {
171
0
  if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0)
172
0
    return eQueueKindUnknown;
173
174
0
  QueueKind kind = eQueueKindUnknown;
175
0
  ReadLibdispatchOffsets();
176
0
  if (m_libdispatch_offsets.IsValid() &&
177
0
      m_libdispatch_offsets.dqo_version >= 4) {
178
0
    Status error;
179
0
    uint64_t width = m_process->ReadUnsignedIntegerFromMemory(
180
0
        dispatch_queue_addr + m_libdispatch_offsets.dqo_width,
181
0
        m_libdispatch_offsets.dqo_width_size, 0, error);
182
0
    if (error.Success()) {
183
0
      if (width == 1) {
184
0
        kind = eQueueKindSerial;
185
0
      }
186
0
      if (width > 1) {
187
0
        kind = eQueueKindConcurrent;
188
0
      }
189
0
    }
190
0
  }
191
0
  return kind;
192
0
}
193
194
void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints(
195
2.38k
    lldb_private::StructuredData::ObjectSP dict_sp) {
196
2.38k
  StructuredData::Dictionary *dict = dict_sp->GetAsDictionary();
197
2.38k
  if (dict) {
198
2.38k
    ReadLibpthreadOffsets();
199
2.38k
    if (m_libpthread_offsets.IsValid()) {
200
2.37k
      dict->AddIntegerItem("plo_pthread_tsd_base_offset",
201
2.37k
                           m_libpthread_offsets.plo_pthread_tsd_base_offset);
202
2.37k
      dict->AddIntegerItem(
203
2.37k
          "plo_pthread_tsd_base_address_offset",
204
2.37k
          m_libpthread_offsets.plo_pthread_tsd_base_address_offset);
205
2.37k
      dict->AddIntegerItem("plo_pthread_tsd_entry_size",
206
2.37k
                           m_libpthread_offsets.plo_pthread_tsd_entry_size);
207
2.37k
    }
208
209
2.38k
    ReadLibdispatchTSDIndexes();
210
2.38k
    if (m_libdispatch_tsd_indexes.IsValid()) {
211
2.37k
      dict->AddIntegerItem("dti_queue_index",
212
2.37k
                           m_libdispatch_tsd_indexes.dti_queue_index);
213
2.37k
      dict->AddIntegerItem("dti_voucher_index",
214
2.37k
                           m_libdispatch_tsd_indexes.dti_voucher_index);
215
2.37k
      dict->AddIntegerItem("dti_qos_class_index",
216
2.37k
                           m_libdispatch_tsd_indexes.dti_qos_class_index);
217
2.37k
    }
218
2.38k
  }
219
2.38k
}
220
221
54
bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) {
222
54
  if (thread_sp && thread_sp->GetStackFrameCount() > 0 &&
223
54
      thread_sp->GetFrameWithConcreteFrameIndex(0)) {
224
54
    const SymbolContext sym_ctx(
225
54
        thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext(
226
54
            eSymbolContextSymbol));
227
54
    static ConstString g_select_symbol("__select");
228
54
    if (sym_ctx.GetFunctionName() == g_select_symbol) {
229
3
      return false;
230
3
    }
231
54
  }
232
51
  return true;
233
54
}
234
235
lldb::queue_id_t
236
0
SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) {
237
0
  queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
238
239
0
  if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
240
0
    return queue_id;
241
242
0
  ReadLibdispatchOffsets();
243
0
  if (m_libdispatch_offsets.IsValid()) {
244
    // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
245
    // thread - deref it to get the address of the dispatch_queue_t structure
246
    // for this thread's queue.
247
0
    Status error;
248
0
    uint64_t dispatch_queue_addr =
249
0
        m_process->ReadPointerFromMemory(dispatch_qaddr, error);
250
0
    if (error.Success()) {
251
0
      addr_t serialnum_address =
252
0
          dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;
253
0
      queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory(
254
0
          serialnum_address, m_libdispatch_offsets.dqo_serialnum_size,
255
0
          LLDB_INVALID_QUEUE_ID, error);
256
0
      if (error.Success()) {
257
0
        queue_id = serialnum;
258
0
      }
259
0
    }
260
0
  }
261
262
0
  return queue_id;
263
0
}
264
265
2
void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
266
2
  if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)
267
0
    return;
268
269
2
  static ConstString g_dispatch_queue_offsets_symbol_name(
270
2
      "dispatch_queue_offsets");
271
2
  const Symbol *dispatch_queue_offsets_symbol = nullptr;
272
273
  // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6
274
  // ("Snow Leopard")
275
2
  ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib"));
276
2
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
277
2
      libSystem_module_spec));
278
2
  if (module_sp)
279
2
    dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
280
2
        g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
281
282
  // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")
283
  // and later
284
2
  if (dispatch_queue_offsets_symbol == nullptr) {
285
2
    ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib"));
286
2
    module_sp = m_process->GetTarget().GetImages().FindFirstModule(
287
2
        libdispatch_module_spec);
288
2
    if (module_sp)
289
2
      dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
290
2
          g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
291
2
  }
292
2
  if (dispatch_queue_offsets_symbol)
293
2
    m_dispatch_queue_offsets_addr =
294
2
        dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget());
295
2
}
296
297
2
void SystemRuntimeMacOSX::ReadLibdispatchOffsets() {
298
2
  if (m_libdispatch_offsets.IsValid())
299
0
    return;
300
301
2
  ReadLibdispatchOffsetsAddress();
302
303
2
  uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)];
304
2
  DataExtractor data(memory_buffer, sizeof(memory_buffer),
305
2
                     m_process->GetByteOrder(),
306
2
                     m_process->GetAddressByteSize());
307
308
2
  Status error;
309
2
  if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer,
310
2
                            sizeof(memory_buffer),
311
2
                            error) == sizeof(memory_buffer)) {
312
2
    lldb::offset_t data_offset = 0;
313
314
    // The struct LibdispatchOffsets is a series of uint16_t's - extract them
315
    // all in one big go.
316
2
    data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version,
317
2
                sizeof(struct LibdispatchOffsets) / sizeof(uint16_t));
318
2
  }
319
2
}
320
321
1.20k
void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() {
322
1.20k
  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)
323
0
    return;
324
325
1.20k
  static ConstString g_libpthread_layout_offsets_symbol_name(
326
1.20k
      "pthread_layout_offsets");
327
1.20k
  const Symbol *libpthread_layout_offsets_symbol = nullptr;
328
329
1.20k
  ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib"));
330
1.20k
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
331
1.20k
      libpthread_module_spec));
332
1.20k
  if (module_sp) {
333
1.19k
    libpthread_layout_offsets_symbol =
334
1.19k
        module_sp->FindFirstSymbolWithNameAndType(
335
1.19k
            g_libpthread_layout_offsets_symbol_name, eSymbolTypeData);
336
1.19k
    if (libpthread_layout_offsets_symbol) {
337
1.19k
      m_libpthread_layout_offsets_addr =
338
1.19k
          libpthread_layout_offsets_symbol->GetLoadAddress(
339
1.19k
              &m_process->GetTarget());
340
1.19k
    }
341
1.19k
  }
342
1.20k
}
343
344
2.38k
void SystemRuntimeMacOSX::ReadLibpthreadOffsets() {
345
2.38k
  if (m_libpthread_offsets.IsValid())
346
1.18k
    return;
347
348
1.20k
  ReadLibpthreadOffsetsAddress();
349
350
1.20k
  if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) {
351
1.19k
    uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)];
352
1.19k
    DataExtractor data(memory_buffer, sizeof(memory_buffer),
353
1.19k
                       m_process->GetByteOrder(),
354
1.19k
                       m_process->GetAddressByteSize());
355
1.19k
    Status error;
356
1.19k
    if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer,
357
1.19k
                              sizeof(memory_buffer),
358
1.19k
                              error) == sizeof(memory_buffer)) {
359
1.19k
      lldb::offset_t data_offset = 0;
360
361
      // The struct LibpthreadOffsets is a series of uint16_t's - extract them
362
      // all in one big go.
363
1.19k
      data.GetU16(&data_offset, &m_libpthread_offsets.plo_version,
364
1.19k
                  sizeof(struct LibpthreadOffsets) / sizeof(uint16_t));
365
1.19k
    }
366
1.19k
  }
367
1.20k
}
368
369
1.20k
void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() {
370
1.20k
  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
371
0
    return;
372
373
1.20k
  static ConstString g_libdispatch_tsd_indexes_symbol_name(
374
1.20k
      "dispatch_tsd_indexes");
375
1.20k
  const Symbol *libdispatch_tsd_indexes_symbol = nullptr;
376
377
1.20k
  ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib"));
378
1.20k
  ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
379
1.20k
      libpthread_module_spec));
380
1.20k
  if (module_sp) {
381
1.19k
    libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType(
382
1.19k
        g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData);
383
1.19k
    if (libdispatch_tsd_indexes_symbol) {
384
1.19k
      m_dispatch_tsd_indexes_addr =
385
1.19k
          libdispatch_tsd_indexes_symbol->GetLoadAddress(
386
1.19k
              &m_process->GetTarget());
387
1.19k
    }
388
1.19k
  }
389
1.20k
}
390
391
2.38k
void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {
392
2.38k
  if (m_libdispatch_tsd_indexes.IsValid())
393
1.18k
    return;
394
395
1.20k
  ReadLibdispatchTSDIndexesAddress();
396
397
1.20k
  if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
398
399
// We don't need to check the version number right now, it will be at least 2,
400
// but keep this code around to fetch just the version # for the future where
401
// we need to fetch alternate versions of the struct.
402
#if 0
403
        uint16_t dti_version = 2;
404
        Address dti_struct_addr;
405
        if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr))
406
        {
407
            Status error;
408
            uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);
409
            if (error.Success() && dti_version != UINT16_MAX)
410
            {
411
                dti_version = version;
412
            }
413
        }
414
#endif
415
416
1.19k
    TypeSystemClang *ast_ctx =
417
1.19k
        ScratchTypeSystemClang::GetForTarget(m_process->GetTarget());
418
1.19k
    if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
419
1.19k
      CompilerType uint16 =
420
1.19k
          ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
421
1.19k
      CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(
422
1.19k
          nullptr, OptionalClangModuleID(), lldb::eAccessPublic,
423
1.19k
          "__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct,
424
1.19k
          lldb::eLanguageTypeC);
425
426
1.19k
      TypeSystemClang::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);
427
1.19k
      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,
428
1.19k
                                            "dti_version", uint16,
429
1.19k
                                            lldb::eAccessPublic, 0);
430
1.19k
      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,
431
1.19k
                                            "dti_queue_index", uint16,
432
1.19k
                                            lldb::eAccessPublic, 0);
433
1.19k
      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,
434
1.19k
                                            "dti_voucher_index", uint16,
435
1.19k
                                            lldb::eAccessPublic, 0);
436
1.19k
      TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s,
437
1.19k
                                            "dti_qos_class_index", uint16,
438
1.19k
                                            lldb::eAccessPublic, 0);
439
1.19k
      TypeSystemClang::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s);
440
441
1.19k
      ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr,
442
1.19k
                                        dispatch_tsd_indexes_s);
443
444
1.19k
      m_libdispatch_tsd_indexes.dti_version =
445
1.19k
          struct_reader.GetField<uint16_t>(ConstString("dti_version"));
446
1.19k
      m_libdispatch_tsd_indexes.dti_queue_index =
447
1.19k
          struct_reader.GetField<uint16_t>(ConstString("dti_queue_index"));
448
1.19k
      m_libdispatch_tsd_indexes.dti_voucher_index =
449
1.19k
          struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index"));
450
1.19k
      m_libdispatch_tsd_indexes.dti_qos_class_index =
451
1.19k
          struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index"));
452
1.19k
    }
453
1.19k
  }
454
1.20k
}
455
456
ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
457
0
                                                         ConstString type) {
458
0
  ThreadSP originating_thread_sp;
459
0
  if (BacktraceRecordingHeadersInitialized() && type == "libdispatch") {
460
0
    Status error;
461
462
    // real_thread is either an actual, live thread (in which case we need to
463
    // call into libBacktraceRecording to find its originator) or it is an
464
    // extended backtrace itself, in which case we get the token from it and
465
    // call into libBacktraceRecording to find the originator of that token.
466
467
0
    if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) {
468
0
      originating_thread_sp = GetExtendedBacktraceFromItemRef(
469
0
          real_thread->GetExtendedBacktraceToken());
470
0
    } else {
471
0
      ThreadSP cur_thread_sp(
472
0
          m_process->GetThreadList().GetExpressionExecutionThread());
473
0
      AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret =
474
0
          m_get_thread_item_info_handler.GetThreadItemInfo(
475
0
              *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free,
476
0
              m_page_to_free_size, error);
477
0
      m_page_to_free = LLDB_INVALID_ADDRESS;
478
0
      m_page_to_free_size = 0;
479
0
      if (ret.item_buffer_ptr != 0 &&
480
0
          ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
481
0
          ret.item_buffer_size > 0) {
482
0
        DataBufferHeap data(ret.item_buffer_size, 0);
483
0
        if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
484
0
                                  ret.item_buffer_size, error) &&
485
0
            error.Success()) {
486
0
          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
487
0
                                  m_process->GetByteOrder(),
488
0
                                  m_process->GetAddressByteSize());
489
0
          ItemInfo item = ExtractItemInfoFromBuffer(extractor);
490
0
          originating_thread_sp = std::make_shared<HistoryThread>(
491
0
              *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);
492
0
          originating_thread_sp->SetExtendedBacktraceToken(
493
0
              item.item_that_enqueued_this);
494
0
          originating_thread_sp->SetQueueName(
495
0
              item.enqueuing_queue_label.c_str());
496
0
          originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
497
          //                    originating_thread_sp->SetThreadName
498
          //                    (item.enqueuing_thread_label.c_str());
499
0
        }
500
0
        m_page_to_free = ret.item_buffer_ptr;
501
0
        m_page_to_free_size = ret.item_buffer_size;
502
0
      }
503
0
    }
504
0
  }
505
0
  return originating_thread_sp;
506
0
}
507
508
ThreadSP
509
0
SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) {
510
0
  ThreadSP return_thread_sp;
511
512
0
  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
513
0
  ThreadSP cur_thread_sp(
514
0
      m_process->GetThreadList().GetExpressionExecutionThread());
515
0
  Status error;
516
0
  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
517
0
                                            m_page_to_free, m_page_to_free_size,
518
0
                                            error);
519
0
  m_page_to_free = LLDB_INVALID_ADDRESS;
520
0
  m_page_to_free_size = 0;
521
0
  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
522
0
      ret.item_buffer_size > 0) {
523
0
    DataBufferHeap data(ret.item_buffer_size, 0);
524
0
    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
525
0
                              ret.item_buffer_size, error) &&
526
0
        error.Success()) {
527
0
      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
528
0
                              m_process->GetByteOrder(),
529
0
                              m_process->GetAddressByteSize());
530
0
      ItemInfo item = ExtractItemInfoFromBuffer(extractor);
531
0
      return_thread_sp = std::make_shared<HistoryThread>(
532
0
          *m_process, item.enqueuing_thread_id, item.enqueuing_callstack);
533
0
      return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this);
534
0
      return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str());
535
0
      return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
536
      //            return_thread_sp->SetThreadName
537
      //            (item.enqueuing_thread_label.c_str());
538
539
0
      m_page_to_free = ret.item_buffer_ptr;
540
0
      m_page_to_free_size = ret.item_buffer_size;
541
0
    }
542
0
  }
543
0
  return return_thread_sp;
544
0
}
545
546
ThreadSP
547
SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp,
548
0
                                                      ConstString type) {
549
0
  ThreadSP extended_thread_sp;
550
0
  if (type != "libdispatch")
551
0
    return extended_thread_sp;
552
553
0
  extended_thread_sp = std::make_shared<HistoryThread>(
554
0
      *m_process, queue_item_sp->GetEnqueueingThreadID(),
555
0
      queue_item_sp->GetEnqueueingBacktrace());
556
0
  extended_thread_sp->SetExtendedBacktraceToken(
557
0
      queue_item_sp->GetItemThatEnqueuedThis());
558
0
  extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str());
559
0
  extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID());
560
  //    extended_thread_sp->SetThreadName
561
  //    (queue_item_sp->GetThreadLabel().c_str());
562
563
0
  return extended_thread_sp;
564
0
}
565
566
/* Returns true if we were able to get the version / offset information
567
 * out of libBacktraceRecording.  false means we were unable to retrieve
568
 * this; the queue_info_version field will be 0.
569
 */
570
571
3
bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() {
572
3
  if (m_lib_backtrace_recording_info.queue_info_version != 0)
573
0
    return true;
574
575
3
  addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
576
3
  addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
577
3
  addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
578
3
  addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
579
3
  Target &target = m_process->GetTarget();
580
581
3
  static ConstString introspection_dispatch_queue_info_version(
582
3
      "__introspection_dispatch_queue_info_version");
583
3
  SymbolContextList sc_list;
584
3
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
585
3
      introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list);
586
3
  if (!sc_list.IsEmpty()) {
587
0
    SymbolContext sc;
588
0
    sc_list.GetContextAtIndex(0, sc);
589
0
    AddressRange addr_range;
590
0
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
591
0
    queue_info_version_address =
592
0
        addr_range.GetBaseAddress().GetLoadAddress(&target);
593
0
  }
594
3
  sc_list.Clear();
595
596
3
  static ConstString introspection_dispatch_queue_info_data_offset(
597
3
      "__introspection_dispatch_queue_info_data_offset");
598
3
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
599
3
      introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list);
600
3
  if (!sc_list.IsEmpty()) {
601
0
    SymbolContext sc;
602
0
    sc_list.GetContextAtIndex(0, sc);
603
0
    AddressRange addr_range;
604
0
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
605
0
    queue_info_data_offset_address =
606
0
        addr_range.GetBaseAddress().GetLoadAddress(&target);
607
0
  }
608
3
  sc_list.Clear();
609
610
3
  static ConstString introspection_dispatch_item_info_version(
611
3
      "__introspection_dispatch_item_info_version");
612
3
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
613
3
      introspection_dispatch_item_info_version, eSymbolTypeData, sc_list);
614
3
  if (!sc_list.IsEmpty()) {
615
0
    SymbolContext sc;
616
0
    sc_list.GetContextAtIndex(0, sc);
617
0
    AddressRange addr_range;
618
0
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
619
0
    item_info_version_address =
620
0
        addr_range.GetBaseAddress().GetLoadAddress(&target);
621
0
  }
622
3
  sc_list.Clear();
623
624
3
  static ConstString introspection_dispatch_item_info_data_offset(
625
3
      "__introspection_dispatch_item_info_data_offset");
626
3
  m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
627
3
      introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list);
628
3
  if (!sc_list.IsEmpty()) {
629
0
    SymbolContext sc;
630
0
    sc_list.GetContextAtIndex(0, sc);
631
0
    AddressRange addr_range;
632
0
    sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
633
0
    item_info_data_offset_address =
634
0
        addr_range.GetBaseAddress().GetLoadAddress(&target);
635
0
  }
636
637
3
  if (queue_info_version_address != LLDB_INVALID_ADDRESS &&
638
3
      
queue_info_data_offset_address != 0
LLDB_INVALID_ADDRESS0
&&
639
3
      
item_info_version_address != 0
LLDB_INVALID_ADDRESS0
&&
640
3
      
item_info_data_offset_address != 0
LLDB_INVALID_ADDRESS0
) {
641
0
    Status error;
642
0
    m_lib_backtrace_recording_info.queue_info_version =
643
0
        m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2,
644
0
                                                 0, error);
645
0
    if (error.Success()) {
646
0
      m_lib_backtrace_recording_info.queue_info_data_offset =
647
0
          m_process->ReadUnsignedIntegerFromMemory(
648
0
              queue_info_data_offset_address, 2, 0, error);
649
0
      if (error.Success()) {
650
0
        m_lib_backtrace_recording_info.item_info_version =
651
0
            m_process->ReadUnsignedIntegerFromMemory(item_info_version_address,
652
0
                                                     2, 0, error);
653
0
        if (error.Success()) {
654
0
          m_lib_backtrace_recording_info.item_info_data_offset =
655
0
              m_process->ReadUnsignedIntegerFromMemory(
656
0
                  item_info_data_offset_address, 2, 0, error);
657
0
          if (!error.Success()) {
658
0
            m_lib_backtrace_recording_info.queue_info_version = 0;
659
0
          }
660
0
        } else {
661
0
          m_lib_backtrace_recording_info.queue_info_version = 0;
662
0
        }
663
0
      } else {
664
0
        m_lib_backtrace_recording_info.queue_info_version = 0;
665
0
      }
666
0
    }
667
0
  }
668
669
3
  return m_lib_backtrace_recording_info.queue_info_version != 0;
670
3
}
671
672
const std::vector<ConstString> &
673
0
SystemRuntimeMacOSX::GetExtendedBacktraceTypes() {
674
0
  if (m_types.size() == 0) {
675
0
    m_types.push_back(ConstString("libdispatch"));
676
    // We could have pthread as another type in the future if we have a way of
677
    // gathering that information & it's useful to distinguish between them.
678
0
  }
679
0
  return m_types;
680
0
}
681
682
void SystemRuntimeMacOSX::PopulateQueueList(
683
3
    lldb_private::QueueList &queue_list) {
684
3
  if (BacktraceRecordingHeadersInitialized()) {
685
0
    AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
686
0
    ThreadSP cur_thread_sp(
687
0
        m_process->GetThreadList().GetExpressionExecutionThread());
688
0
    if (cur_thread_sp) {
689
0
      Status error;
690
0
      queue_info_pointer = m_get_queues_handler.GetCurrentQueues(
691
0
          *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
692
0
      m_page_to_free = LLDB_INVALID_ADDRESS;
693
0
      m_page_to_free_size = 0;
694
0
      if (error.Success()) {
695
696
0
        if (queue_info_pointer.count > 0 &&
697
0
            queue_info_pointer.queues_buffer_size > 0 &&
698
0
            queue_info_pointer.queues_buffer_ptr != 0 &&
699
0
            queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) {
700
0
          PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr,
701
0
                                    queue_info_pointer.queues_buffer_size,
702
0
                                    queue_info_pointer.count, queue_list);
703
0
        }
704
0
      }
705
0
    }
706
0
  }
707
708
  // We either didn't have libBacktraceRecording (and need to create the queues
709
  // list based on threads) or we did get the queues list from
710
  // libBacktraceRecording but some special queues may not be included in its
711
  // information.  This is needed because libBacktraceRecording will only list
712
  // queues with pending or running items by default - but the magic com.apple
713
  // .main-thread queue on thread 1 is always around.
714
715
42
  for (ThreadSP thread_sp : m_process->Threads()) {
716
42
    if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) {
717
39
      if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) {
718
39
        if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() ==
719
39
            nullptr) {
720
30
          QueueSP queue_sp(new Queue(m_process->shared_from_this(),
721
30
                                     thread_sp->GetQueueID(),
722
30
                                     thread_sp->GetQueueName()));
723
30
          if (thread_sp->ThreadHasQueueInformation()) {
724
30
            queue_sp->SetKind(thread_sp->GetQueueKind());
725
30
            queue_sp->SetLibdispatchQueueAddress(
726
30
                thread_sp->GetQueueLibdispatchQueueAddress());
727
30
            queue_list.AddQueue(queue_sp);
728
30
          } else {
729
0
            queue_sp->SetKind(
730
0
                GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress()));
731
0
            queue_sp->SetLibdispatchQueueAddress(
732
0
                thread_sp->GetQueueLibdispatchQueueAddress());
733
0
            queue_list.AddQueue(queue_sp);
734
0
          }
735
30
        }
736
39
      }
737
39
    }
738
42
  }
739
3
}
740
741
// Returns either an array of introspection_dispatch_item_info_ref's for the
742
// pending items on a queue or an array introspection_dispatch_item_info_ref's
743
// and code addresses for the pending items on a queue.  The information about
744
// each of these pending items then needs to be fetched individually by passing
745
// the ref to libBacktraceRecording.
746
747
SystemRuntimeMacOSX::PendingItemsForQueue
748
0
SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) {
749
0
  PendingItemsForQueue pending_item_refs;
750
0
  AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
751
0
  ThreadSP cur_thread_sp(
752
0
      m_process->GetThreadList().GetExpressionExecutionThread());
753
0
  if (cur_thread_sp) {
754
0
    Status error;
755
0
    pending_items_pointer = m_get_pending_items_handler.GetPendingItems(
756
0
        *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size,
757
0
        error);
758
0
    m_page_to_free = LLDB_INVALID_ADDRESS;
759
0
    m_page_to_free_size = 0;
760
0
    if (error.Success()) {
761
0
      if (pending_items_pointer.count > 0 &&
762
0
          pending_items_pointer.items_buffer_size > 0 &&
763
0
          pending_items_pointer.items_buffer_ptr != 0 &&
764
0
          pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) {
765
0
        DataBufferHeap data(pending_items_pointer.items_buffer_size, 0);
766
0
        if (m_process->ReadMemory(
767
0
                pending_items_pointer.items_buffer_ptr, data.GetBytes(),
768
0
                pending_items_pointer.items_buffer_size, error)) {
769
0
          DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
770
0
                                  m_process->GetByteOrder(),
771
0
                                  m_process->GetAddressByteSize());
772
773
          // We either have an array of
774
          //    void* item_ref
775
          // (old style) or we have a structure returned which looks like
776
          //
777
          // struct introspection_dispatch_pending_item_info_s {
778
          //   void *item_ref;
779
          //   void *function_or_block;
780
          // };
781
          //
782
          // struct introspection_dispatch_pending_items_array_s {
783
          //   uint32_t version;
784
          //   uint32_t size_of_item_info;
785
          //   introspection_dispatch_pending_item_info_s items[];
786
          //   }
787
788
0
          offset_t offset = 0;
789
0
          int i = 0;
790
0
          uint32_t version = extractor.GetU32(&offset);
791
0
          if (version == 1) {
792
0
            pending_item_refs.new_style = true;
793
0
            uint32_t item_size = extractor.GetU32(&offset);
794
0
            uint32_t start_of_array_offset = offset;
795
0
            while (offset < pending_items_pointer.items_buffer_size &&
796
0
                   static_cast<size_t>(i) < pending_items_pointer.count) {
797
0
              offset = start_of_array_offset + (i * item_size);
798
0
              ItemRefAndCodeAddress item;
799
0
              item.item_ref = extractor.GetAddress(&offset);
800
0
              item.code_address = extractor.GetAddress(&offset);
801
0
              pending_item_refs.item_refs_and_code_addresses.push_back(item);
802
0
              i++;
803
0
            }
804
0
          } else {
805
0
            offset = 0;
806
0
            pending_item_refs.new_style = false;
807
0
            while (offset < pending_items_pointer.items_buffer_size &&
808
0
                   static_cast<size_t>(i) < pending_items_pointer.count) {
809
0
              ItemRefAndCodeAddress item;
810
0
              item.item_ref = extractor.GetAddress(&offset);
811
0
              item.code_address = LLDB_INVALID_ADDRESS;
812
0
              pending_item_refs.item_refs_and_code_addresses.push_back(item);
813
0
              i++;
814
0
            }
815
0
          }
816
0
        }
817
0
        m_page_to_free = pending_items_pointer.items_buffer_ptr;
818
0
        m_page_to_free_size = pending_items_pointer.items_buffer_size;
819
0
      }
820
0
    }
821
0
  }
822
0
  return pending_item_refs;
823
0
}
824
825
0
void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) {
826
0
  if (BacktraceRecordingHeadersInitialized()) {
827
0
    PendingItemsForQueue pending_item_refs =
828
0
        GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress());
829
0
    for (ItemRefAndCodeAddress pending_item :
830
0
         pending_item_refs.item_refs_and_code_addresses) {
831
0
      Address addr;
832
0
      m_process->GetTarget().ResolveLoadAddress(pending_item.code_address,
833
0
                                                addr);
834
0
      QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(),
835
0
                                              m_process->shared_from_this(),
836
0
                                              pending_item.item_ref, addr));
837
0
      queue->PushPendingQueueItem(queue_item_sp);
838
0
    }
839
0
  }
840
0
}
841
842
void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item,
843
0
                                            addr_t item_ref) {
844
0
  AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
845
846
0
  ThreadSP cur_thread_sp(
847
0
      m_process->GetThreadList().GetExpressionExecutionThread());
848
0
  Status error;
849
0
  ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
850
0
                                            m_page_to_free, m_page_to_free_size,
851
0
                                            error);
852
0
  m_page_to_free = LLDB_INVALID_ADDRESS;
853
0
  m_page_to_free_size = 0;
854
0
  if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
855
0
      ret.item_buffer_size > 0) {
856
0
    DataBufferHeap data(ret.item_buffer_size, 0);
857
0
    if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
858
0
                              ret.item_buffer_size, error) &&
859
0
        error.Success()) {
860
0
      DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
861
0
                              m_process->GetByteOrder(),
862
0
                              m_process->GetAddressByteSize());
863
0
      ItemInfo item = ExtractItemInfoFromBuffer(extractor);
864
0
      queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this);
865
0
      queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id);
866
0
      queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum);
867
0
      queue_item->SetStopID(item.stop_id);
868
0
      queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack);
869
0
      queue_item->SetThreadLabel(item.enqueuing_thread_label);
870
0
      queue_item->SetQueueLabel(item.enqueuing_queue_label);
871
0
      queue_item->SetTargetQueueLabel(item.target_queue_label);
872
0
    }
873
0
    m_page_to_free = ret.item_buffer_ptr;
874
0
    m_page_to_free_size = ret.item_buffer_size;
875
0
  }
876
0
}
877
878
void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR(
879
    lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count,
880
0
    lldb_private::QueueList &queue_list) {
881
0
  Status error;
882
0
  DataBufferHeap data(queues_buffer_size, 0);
883
0
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME));
884
0
  if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size,
885
0
                            error) == queues_buffer_size &&
886
0
      error.Success()) {
887
    // We've read the information out of inferior memory; free it on the next
888
    // call we make
889
0
    m_page_to_free = queues_buffer;
890
0
    m_page_to_free_size = queues_buffer_size;
891
892
0
    DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
893
0
                            m_process->GetByteOrder(),
894
0
                            m_process->GetAddressByteSize());
895
0
    offset_t offset = 0;
896
0
    uint64_t queues_read = 0;
897
898
    // The information about the queues is stored in this format (v1): typedef
899
    // struct introspection_dispatch_queue_info_s {
900
    //     uint32_t offset_to_next;
901
    //     dispatch_queue_t queue;
902
    //     uint64_t serialnum;     // queue's serialnum in the process, as
903
    //     provided by libdispatch
904
    //     uint32_t running_work_items_count;
905
    //     uint32_t pending_work_items_count;
906
    //
907
    //     char data[];     // Starting here, we have variable-length data:
908
    //     // char queue_label[];
909
    // } introspection_dispatch_queue_info_s;
910
911
0
    while (queues_read < count && offset < queues_buffer_size) {
912
0
      offset_t start_of_this_item = offset;
913
914
0
      uint32_t offset_to_next = extractor.GetU32(&offset);
915
916
0
      offset += 4; // Skip over the 4 bytes of reserved space
917
0
      addr_t queue = extractor.GetAddress(&offset);
918
0
      uint64_t serialnum = extractor.GetU64(&offset);
919
0
      uint32_t running_work_items_count = extractor.GetU32(&offset);
920
0
      uint32_t pending_work_items_count = extractor.GetU32(&offset);
921
922
      // Read the first field of the variable length data
923
0
      offset = start_of_this_item +
924
0
               m_lib_backtrace_recording_info.queue_info_data_offset;
925
0
      const char *queue_label = extractor.GetCStr(&offset);
926
0
      if (queue_label == nullptr)
927
0
        queue_label = "";
928
929
0
      offset_t start_of_next_item = start_of_this_item + offset_to_next;
930
0
      offset = start_of_next_item;
931
932
0
      LLDB_LOGF(log,
933
0
                "SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added "
934
0
                "queue with dispatch_queue_t 0x%" PRIx64
935
0
                ", serial number 0x%" PRIx64
936
0
                ", running items %d, pending items %d, name '%s'",
937
0
                queue, serialnum, running_work_items_count,
938
0
                pending_work_items_count, queue_label);
939
940
0
      QueueSP queue_sp(
941
0
          new Queue(m_process->shared_from_this(), serialnum, queue_label));
942
0
      queue_sp->SetNumRunningWorkItems(running_work_items_count);
943
0
      queue_sp->SetNumPendingWorkItems(pending_work_items_count);
944
0
      queue_sp->SetLibdispatchQueueAddress(queue);
945
0
      queue_sp->SetKind(GetQueueKind(queue));
946
0
      queue_list.AddQueue(queue_sp);
947
0
      queues_read++;
948
0
    }
949
0
  }
950
0
}
951
952
SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer(
953
0
    lldb_private::DataExtractor &extractor) {
954
0
  ItemInfo item;
955
956
0
  offset_t offset = 0;
957
958
0
  item.item_that_enqueued_this = extractor.GetAddress(&offset);
959
0
  item.function_or_block = extractor.GetAddress(&offset);
960
0
  item.enqueuing_thread_id = extractor.GetU64(&offset);
961
0
  item.enqueuing_queue_serialnum = extractor.GetU64(&offset);
962
0
  item.target_queue_serialnum = extractor.GetU64(&offset);
963
0
  item.enqueuing_callstack_frame_count = extractor.GetU32(&offset);
964
0
  item.stop_id = extractor.GetU32(&offset);
965
966
0
  offset = m_lib_backtrace_recording_info.item_info_data_offset;
967
968
0
  for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) {
969
0
    item.enqueuing_callstack.push_back(extractor.GetAddress(&offset));
970
0
  }
971
0
  item.enqueuing_thread_label = extractor.GetCStr(&offset);
972
0
  item.enqueuing_queue_label = extractor.GetCStr(&offset);
973
0
  item.target_queue_label = extractor.GetCStr(&offset);
974
975
0
  return item;
976
0
}
977
978
3.44k
void SystemRuntimeMacOSX::Initialize() {
979
3.44k
  PluginManager::RegisterPlugin(
980
3.44k
      GetPluginNameStatic(),
981
3.44k
      "System runtime plugin for Mac OS X native libraries.", CreateInstance);
982
3.44k
}
983
984
3.43k
void SystemRuntimeMacOSX::Terminate() {
985
3.43k
  PluginManager::UnregisterPlugin(CreateInstance);
986
3.43k
}