blob: 513bdb3cc5c71a6ff7e5a75ddbdf3bcf6613ecc8 [file] [log] [blame]
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Jason Molendaa7b5afa2013-11-15 00:17:32 +00006//
7//===----------------------------------------------------------------------===//
8
Kate Stoneb9c1b512016-09-06 20:57:50 +00009#include "Plugins/Process/Utility/HistoryThread.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000010#include "lldb/Breakpoint/StoppointCallbackContext.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000011#include "lldb/Core/Module.h"
12#include "lldb/Core/ModuleSpec.h"
13#include "lldb/Core/PluginManager.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000014#include "lldb/Core/Section.h"
Zachary Turner88c6b622015-03-03 18:34:26 +000015#include "lldb/Symbol/ClangASTContext.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000016#include "lldb/Symbol/ObjectFile.h"
17#include "lldb/Symbol/SymbolContext.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "lldb/Target/Process.h"
Zachary Turner01c32432017-02-14 19:06:07 +000019#include "lldb/Target/ProcessStructReader.h"
Jason Molenda5e8dce42013-12-13 00:29:16 +000020#include "lldb/Target/Queue.h"
21#include "lldb/Target/QueueList.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000022#include "lldb/Target/Target.h"
23#include "lldb/Target/Thread.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000024#include "lldb/Utility/DataBufferHeap.h"
25#include "lldb/Utility/DataExtractor.h"
Zachary Turner5713a052017-03-22 18:40:07 +000026#include "lldb/Utility/FileSpec.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000027#include "lldb/Utility/Log.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000028#include "lldb/Utility/StreamString.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000029
Jason Molendaa7b5afa2013-11-15 00:17:32 +000030#include "SystemRuntimeMacOSX.h"
31
Jonas Devlieghere796ac802019-02-11 23:13:08 +000032#include <memory>
33
Jason Molendaa7b5afa2013-11-15 00:17:32 +000034using namespace lldb;
35using namespace lldb_private;
36
37//----------------------------------------------------------------------
Adrian Prantl05097242018-04-30 16:49:04 +000038// Create an instance of this class. This function is filled into the plugin
39// info class that gets handed out by the plugin factory and allows the lldb to
40// instantiate an instance of this class.
Jason Molendaa7b5afa2013-11-15 00:17:32 +000041//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000042SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {
43 bool create = false;
44 if (!create) {
45 create = true;
46 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
47 if (exe_module) {
48 ObjectFile *object_file = exe_module->GetObjectFile();
49 if (object_file) {
50 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
51 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +000052 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000053
54 if (create) {
55 const llvm::Triple &triple_ref =
56 process->GetTarget().GetArchitecture().GetTriple();
57 switch (triple_ref.getOS()) {
58 case llvm::Triple::Darwin:
59 case llvm::Triple::MacOSX:
60 case llvm::Triple::IOS:
61 case llvm::Triple::TvOS:
62 case llvm::Triple::WatchOS:
Jason Molenda32762fd2018-10-11 00:28:35 +000063 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 create = triple_ref.getVendor() == llvm::Triple::Apple;
65 break;
66 default:
67 create = false;
68 break;
69 }
70 }
71 }
72
73 if (create)
74 return new SystemRuntimeMacOSX(process);
75 return NULL;
Jason Molendaa7b5afa2013-11-15 00:17:32 +000076}
77
78//----------------------------------------------------------------------
79// Constructor
80//----------------------------------------------------------------------
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000081SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process)
Kate Stoneb9c1b512016-09-06 20:57:50 +000082 : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
83 m_get_queues_handler(process), m_get_pending_items_handler(process),
84 m_get_item_info_handler(process), m_get_thread_item_info_handler(process),
85 m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0),
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000086 m_lib_backtrace_recording_info(),
87 m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS),
88 m_libdispatch_offsets(),
89 m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS),
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS),
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000091 m_libdispatch_tsd_indexes(),
92 m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS),
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 m_libdispatch_voucher_offsets() {}
Jason Molendaa7b5afa2013-11-15 00:17:32 +000094
95//----------------------------------------------------------------------
96// Destructor
97//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000098SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); }
Jason Molendaa7b5afa2013-11-15 00:17:32 +000099
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100void SystemRuntimeMacOSX::Detach() {
101 m_get_queues_handler.Detach();
102 m_get_pending_items_handler.Detach();
103 m_get_item_info_handler.Detach();
104 m_get_thread_item_info_handler.Detach();
Jason Molenda2fd83352014-02-05 05:44:54 +0000105}
106
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000107//----------------------------------------------------------------------
108// Clear out the state of this class.
109//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110void SystemRuntimeMacOSX::Clear(bool clear_process) {
111 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000112
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
114 m_process->ClearBreakpointSiteByID(m_break_id);
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 if (clear_process)
117 m_process = NULL;
118 m_break_id = LLDB_INVALID_BREAK_ID;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000119}
120
Jason Molenda2fd83352014-02-05 05:44:54 +0000121std::string
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) {
123 std::string dispatch_queue_name;
124 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
125 return "";
Jason Molenda2fd83352014-02-05 05:44:54 +0000126
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127 ReadLibdispatchOffsets();
128 if (m_libdispatch_offsets.IsValid()) {
129 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
Adrian Prantl05097242018-04-30 16:49:04 +0000130 // thread - deref it to get the address of the dispatch_queue_t structure
131 // for this thread's queue.
Zachary Turner97206d52017-05-12 04:51:55 +0000132 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 addr_t dispatch_queue_addr =
134 m_process->ReadPointerFromMemory(dispatch_qaddr, error);
135 if (error.Success()) {
136 if (m_libdispatch_offsets.dqo_version >= 4) {
Adrian Prantl05097242018-04-30 16:49:04 +0000137 // libdispatch versions 4+, pointer to dispatch name is in the queue
138 // structure.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 addr_t pointer_to_label_address =
140 dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
141 addr_t label_addr =
142 m_process->ReadPointerFromMemory(pointer_to_label_address, error);
143 if (error.Success()) {
144 m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name,
145 error);
146 }
147 } else {
148 // libdispatch versions 1-3, dispatch name is a fixed width char array
149 // in the queue structure.
150 addr_t label_addr =
151 dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
152 dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0');
153 size_t bytes_read =
154 m_process->ReadMemory(label_addr, &dispatch_queue_name[0],
155 m_libdispatch_offsets.dqo_label_size, error);
156 if (bytes_read < m_libdispatch_offsets.dqo_label_size)
157 dispatch_queue_name.erase(bytes_read);
158 }
Jason Molendaaac16e02014-03-13 02:54:54 +0000159 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000160 }
161 return dispatch_queue_name;
Jason Molendaaac16e02014-03-13 02:54:54 +0000162}
163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress(
165 addr_t dispatch_qaddr) {
166 addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
Zachary Turner97206d52017-05-12 04:51:55 +0000167 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 libdispatch_queue_t_address =
169 m_process->ReadPointerFromMemory(dispatch_qaddr, error);
170 if (!error.Success()) {
171 libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
172 }
173 return libdispatch_queue_t_address;
Jason Molendaaac16e02014-03-13 02:54:54 +0000174}
175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) {
177 if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0)
178 return eQueueKindUnknown;
179
180 QueueKind kind = eQueueKindUnknown;
181 ReadLibdispatchOffsets();
182 if (m_libdispatch_offsets.IsValid() &&
183 m_libdispatch_offsets.dqo_version >= 4) {
Zachary Turner97206d52017-05-12 04:51:55 +0000184 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 uint64_t width = m_process->ReadUnsignedIntegerFromMemory(
186 dispatch_queue_addr + m_libdispatch_offsets.dqo_width,
187 m_libdispatch_offsets.dqo_width_size, 0, error);
188 if (error.Success()) {
189 if (width == 1) {
190 kind = eQueueKindSerial;
191 }
192 if (width > 1) {
193 kind = eQueueKindConcurrent;
194 }
Jason Molenda705b1802014-06-13 02:37:02 +0000195 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 }
197 return kind;
Jason Molenda705b1802014-06-13 02:37:02 +0000198}
199
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints(
201 lldb_private::StructuredData::ObjectSP dict_sp) {
202 StructuredData::Dictionary *dict = dict_sp->GetAsDictionary();
203 if (dict) {
204 ReadLibpthreadOffsets();
205 if (m_libpthread_offsets.IsValid()) {
206 dict->AddIntegerItem("plo_pthread_tsd_base_offset",
207 m_libpthread_offsets.plo_pthread_tsd_base_offset);
208 dict->AddIntegerItem(
209 "plo_pthread_tsd_base_address_offset",
210 m_libpthread_offsets.plo_pthread_tsd_base_address_offset);
211 dict->AddIntegerItem("plo_pthread_tsd_entry_size",
212 m_libpthread_offsets.plo_pthread_tsd_entry_size);
Jason Molendab4892cd2014-05-13 22:02:48 +0000213 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214
215 ReadLibdispatchTSDIndexes();
216 if (m_libdispatch_tsd_indexes.IsValid()) {
217 dict->AddIntegerItem("dti_queue_index",
218 m_libdispatch_tsd_indexes.dti_queue_index);
219 dict->AddIntegerItem("dti_voucher_index",
220 m_libdispatch_tsd_indexes.dti_voucher_index);
221 dict->AddIntegerItem("dti_qos_class_index",
222 m_libdispatch_tsd_indexes.dti_qos_class_index);
223 }
224 }
225}
226
227bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) {
228 if (thread_sp && thread_sp->GetStackFrameCount() > 0 &&
229 thread_sp->GetFrameWithConcreteFrameIndex(0)) {
230 const SymbolContext sym_ctx(
231 thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext(
232 eSymbolContextSymbol));
233 static ConstString g_select_symbol("__select");
234 if (sym_ctx.GetFunctionName() == g_select_symbol) {
235 return false;
236 }
237 }
238 return true;
Jason Molendab4892cd2014-05-13 22:02:48 +0000239}
240
Jason Molenda2fd83352014-02-05 05:44:54 +0000241lldb::queue_id_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) {
243 queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
Jason Molenda2fd83352014-02-05 05:44:54 +0000244
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
Jason Molenda2fd83352014-02-05 05:44:54 +0000246 return queue_id;
Jason Molenda2fd83352014-02-05 05:44:54 +0000247
Kate Stoneb9c1b512016-09-06 20:57:50 +0000248 ReadLibdispatchOffsets();
249 if (m_libdispatch_offsets.IsValid()) {
250 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
Adrian Prantl05097242018-04-30 16:49:04 +0000251 // thread - deref it to get the address of the dispatch_queue_t structure
252 // for this thread's queue.
Zachary Turner97206d52017-05-12 04:51:55 +0000253 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254 uint64_t dispatch_queue_addr =
255 m_process->ReadPointerFromMemory(dispatch_qaddr, error);
256 if (error.Success()) {
257 addr_t serialnum_address =
258 dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;
259 queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory(
260 serialnum_address, m_libdispatch_offsets.dqo_serialnum_size,
261 LLDB_INVALID_QUEUE_ID, error);
262 if (error.Success()) {
263 queue_id = serialnum;
264 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000265 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 }
267
268 return queue_id;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000269}
270
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
272 if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)
273 return;
Jason Molenda705b1802014-06-13 02:37:02 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 static ConstString g_dispatch_queue_offsets_symbol_name(
276 "dispatch_queue_offsets");
277 const Symbol *dispatch_queue_offsets_symbol = NULL;
Jason Molenda705b1802014-06-13 02:37:02 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6
280 // ("Snow Leopard")
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000281 ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
283 libSystem_module_spec));
284 if (module_sp)
285 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
286 g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
287
Adrian Prantl05097242018-04-30 16:49:04 +0000288 // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")
289 // and later
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 if (dispatch_queue_offsets_symbol == NULL) {
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000291 ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 module_sp = m_process->GetTarget().GetImages().FindFirstModule(
293 libdispatch_module_spec);
Jason Molenda705b1802014-06-13 02:37:02 +0000294 if (module_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
296 g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
297 }
298 if (dispatch_queue_offsets_symbol)
299 m_dispatch_queue_offsets_addr =
300 dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget());
Jason Molenda705b1802014-06-13 02:37:02 +0000301}
302
Kate Stoneb9c1b512016-09-06 20:57:50 +0000303void SystemRuntimeMacOSX::ReadLibdispatchOffsets() {
304 if (m_libdispatch_offsets.IsValid())
305 return;
Jason Molenda705b1802014-06-13 02:37:02 +0000306
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 ReadLibdispatchOffsetsAddress();
Jason Molenda705b1802014-06-13 02:37:02 +0000308
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)];
310 DataExtractor data(memory_buffer, sizeof(memory_buffer),
311 m_process->GetByteOrder(),
312 m_process->GetAddressByteSize());
313
Zachary Turner97206d52017-05-12 04:51:55 +0000314 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer,
316 sizeof(memory_buffer),
317 error) == sizeof(memory_buffer)) {
318 lldb::offset_t data_offset = 0;
319
320 // The struct LibdispatchOffsets is a series of uint16_t's - extract them
Adrian Prantl05097242018-04-30 16:49:04 +0000321 // all in one big go.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322 data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version,
323 sizeof(struct LibdispatchOffsets) / sizeof(uint16_t));
324 }
Jason Molenda705b1802014-06-13 02:37:02 +0000325}
326
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() {
328 if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)
329 return;
Jason Molenda705b1802014-06-13 02:37:02 +0000330
Kate Stoneb9c1b512016-09-06 20:57:50 +0000331 static ConstString g_libpthread_layout_offsets_symbol_name(
332 "pthread_layout_offsets");
333 const Symbol *libpthread_layout_offsets_symbol = NULL;
Jason Molenda705b1802014-06-13 02:37:02 +0000334
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000335 ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
337 libpthread_module_spec));
338 if (module_sp) {
339 libpthread_layout_offsets_symbol =
340 module_sp->FindFirstSymbolWithNameAndType(
341 g_libpthread_layout_offsets_symbol_name, eSymbolTypeData);
342 if (libpthread_layout_offsets_symbol) {
343 m_libpthread_layout_offsets_addr =
344 libpthread_layout_offsets_symbol->GetLoadAddress(
345 &m_process->GetTarget());
Jason Molenda705b1802014-06-13 02:37:02 +0000346 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 }
Jason Molenda705b1802014-06-13 02:37:02 +0000348}
349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350void SystemRuntimeMacOSX::ReadLibpthreadOffsets() {
351 if (m_libpthread_offsets.IsValid())
352 return;
Jason Molenda705b1802014-06-13 02:37:02 +0000353
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354 ReadLibpthreadOffsetsAddress();
Jason Molenda705b1802014-06-13 02:37:02 +0000355
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356 if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) {
357 uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)];
358 DataExtractor data(memory_buffer, sizeof(memory_buffer),
359 m_process->GetByteOrder(),
360 m_process->GetAddressByteSize());
Zachary Turner97206d52017-05-12 04:51:55 +0000361 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer,
363 sizeof(memory_buffer),
364 error) == sizeof(memory_buffer)) {
365 lldb::offset_t data_offset = 0;
Jason Molenda59ac67e2014-09-12 00:09:04 +0000366
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 // The struct LibpthreadOffsets is a series of uint16_t's - extract them
Adrian Prantl05097242018-04-30 16:49:04 +0000368 // all in one big go.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 data.GetU16(&data_offset, &m_libpthread_offsets.plo_version,
370 sizeof(struct LibpthreadOffsets) / sizeof(uint16_t));
371 }
372 }
373}
374
375void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() {
376 if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
377 return;
378
379 static ConstString g_libdispatch_tsd_indexes_symbol_name(
380 "dispatch_tsd_indexes");
381 const Symbol *libdispatch_tsd_indexes_symbol = NULL;
382
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000383 ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
385 libpthread_module_spec));
386 if (module_sp) {
387 libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType(
388 g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData);
389 if (libdispatch_tsd_indexes_symbol) {
390 m_dispatch_tsd_indexes_addr =
391 libdispatch_tsd_indexes_symbol->GetLoadAddress(
392 &m_process->GetTarget());
393 }
394 }
395}
396
397void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {
398 if (m_libdispatch_tsd_indexes.IsValid())
399 return;
400
401 ReadLibdispatchTSDIndexesAddress();
402
403 if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
404
405// We don't need to check the version number right now, it will be at least 2,
Adrian Prantl05097242018-04-30 16:49:04 +0000406// but keep this code around to fetch just the version # for the future where
407// we need to fetch alternate versions of the struct.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408#if 0
Jason Molenda705b1802014-06-13 02:37:02 +0000409 uint16_t dti_version = 2;
Jason Molenda59ac67e2014-09-12 00:09:04 +0000410 Address dti_struct_addr;
411 if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr))
Jason Molenda705b1802014-06-13 02:37:02 +0000412 {
Zachary Turner97206d52017-05-12 04:51:55 +0000413 Status error;
Jason Molenda705b1802014-06-13 02:37:02 +0000414 uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);
415 if (error.Success() && dti_version != UINT16_MAX)
416 {
417 dti_version = version;
418 }
419 }
Jason Molenda59ac67e2014-09-12 00:09:04 +0000420#endif
Jason Molenda705b1802014-06-13 02:37:02 +0000421
Kate Stoneb9c1b512016-09-06 20:57:50 +0000422 ClangASTContext *ast_ctx =
423 m_process->GetTarget().GetScratchClangASTContext();
424 if (ast_ctx->getASTContext() &&
425 m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
426 CompilerType uint16 =
427 ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16);
428 CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(
429 nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s",
430 clang::TTK_Struct, lldb::eLanguageTypeC);
Greg Claytond8d4a572015-08-11 21:38:15 +0000431
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);
433 ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
434 "dti_version", uint16,
435 lldb::eAccessPublic, 0);
436 ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
437 "dti_queue_index", uint16,
438 lldb::eAccessPublic, 0);
439 ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
440 "dti_voucher_index", uint16,
441 lldb::eAccessPublic, 0);
442 ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s,
443 "dti_qos_class_index", uint16,
444 lldb::eAccessPublic, 0);
445 ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s);
Jason Molenda59ac67e2014-09-12 00:09:04 +0000446
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447 ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr,
448 dispatch_tsd_indexes_s);
Jason Molenda59ac67e2014-09-12 00:09:04 +0000449
Kate Stoneb9c1b512016-09-06 20:57:50 +0000450 m_libdispatch_tsd_indexes.dti_version =
451 struct_reader.GetField<uint16_t>(ConstString("dti_version"));
452 m_libdispatch_tsd_indexes.dti_queue_index =
453 struct_reader.GetField<uint16_t>(ConstString("dti_queue_index"));
454 m_libdispatch_tsd_indexes.dti_voucher_index =
455 struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index"));
456 m_libdispatch_tsd_indexes.dti_qos_class_index =
457 struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index"));
Jason Molenda705b1802014-06-13 02:37:02 +0000458 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000459 }
Jason Molenda705b1802014-06-13 02:37:02 +0000460}
461
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
463 ConstString type) {
464 ThreadSP originating_thread_sp;
465 if (BacktraceRecordingHeadersInitialized() &&
466 type == ConstString("libdispatch")) {
Zachary Turner97206d52017-05-12 04:51:55 +0000467 Status error;
Jason Molenda2fd83352014-02-05 05:44:54 +0000468
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469 // real_thread is either an actual, live thread (in which case we need to
Adrian Prantl05097242018-04-30 16:49:04 +0000470 // call into libBacktraceRecording to find its originator) or it is an
471 // extended backtrace itself, in which case we get the token from it and
472 // call into libBacktraceRecording to find the originator of that token.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473
474 if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) {
475 originating_thread_sp = GetExtendedBacktraceFromItemRef(
476 real_thread->GetExtendedBacktraceToken());
477 } else {
478 ThreadSP cur_thread_sp(
479 m_process->GetThreadList().GetExpressionExecutionThread());
480 AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret =
481 m_get_thread_item_info_handler.GetThreadItemInfo(
482 *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free,
483 m_page_to_free_size, error);
484 m_page_to_free = LLDB_INVALID_ADDRESS;
485 m_page_to_free_size = 0;
486 if (ret.item_buffer_ptr != 0 &&
487 ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
488 ret.item_buffer_size > 0) {
489 DataBufferHeap data(ret.item_buffer_size, 0);
490 if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
491 ret.item_buffer_size, error) &&
492 error.Success()) {
493 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
494 m_process->GetByteOrder(),
495 m_process->GetAddressByteSize());
496 ItemInfo item = ExtractItemInfoFromBuffer(extractor);
497 bool stop_id_is_valid = true;
498 if (item.stop_id == 0)
499 stop_id_is_valid = false;
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000500 originating_thread_sp = std::make_shared<HistoryThread>(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501 *m_process, item.enqueuing_thread_id, item.enqueuing_callstack,
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000502 item.stop_id, stop_id_is_valid);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000503 originating_thread_sp->SetExtendedBacktraceToken(
504 item.item_that_enqueued_this);
505 originating_thread_sp->SetQueueName(
506 item.enqueuing_queue_label.c_str());
507 originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
508 // originating_thread_sp->SetThreadName
509 // (item.enqueuing_thread_label.c_str());
Jason Molenda2fd83352014-02-05 05:44:54 +0000510 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000511 m_page_to_free = ret.item_buffer_ptr;
512 m_page_to_free_size = ret.item_buffer_size;
513 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000514 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515 }
516 return originating_thread_sp;
Jason Molenda2fd83352014-02-05 05:44:54 +0000517}
518
519ThreadSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000520SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) {
521 ThreadSP return_thread_sp;
Jason Molenda2fd83352014-02-05 05:44:54 +0000522
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
524 ThreadSP cur_thread_sp(
525 m_process->GetThreadList().GetExpressionExecutionThread());
Zachary Turner97206d52017-05-12 04:51:55 +0000526 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527 ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
528 m_page_to_free, m_page_to_free_size,
529 error);
530 m_page_to_free = LLDB_INVALID_ADDRESS;
531 m_page_to_free_size = 0;
532 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
533 ret.item_buffer_size > 0) {
534 DataBufferHeap data(ret.item_buffer_size, 0);
535 if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
536 ret.item_buffer_size, error) &&
537 error.Success()) {
538 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
539 m_process->GetByteOrder(),
540 m_process->GetAddressByteSize());
541 ItemInfo item = ExtractItemInfoFromBuffer(extractor);
542 bool stop_id_is_valid = true;
543 if (item.stop_id == 0)
Jason Molenda2fd83352014-02-05 05:44:54 +0000544 stop_id_is_valid = false;
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000545 return_thread_sp = std::make_shared<HistoryThread>(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 *m_process, item.enqueuing_thread_id, item.enqueuing_callstack,
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000547 item.stop_id, stop_id_is_valid);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000548 return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this);
549 return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str());
550 return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum);
551 // return_thread_sp->SetThreadName
552 // (item.enqueuing_thread_label.c_str());
Jason Molenda2fd83352014-02-05 05:44:54 +0000553
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554 m_page_to_free = ret.item_buffer_ptr;
555 m_page_to_free_size = ret.item_buffer_size;
556 }
557 }
558 return return_thread_sp;
559}
Jason Molenda2fd83352014-02-05 05:44:54 +0000560
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561ThreadSP
562SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp,
563 ConstString type) {
564 ThreadSP extended_thread_sp;
565 if (type != ConstString("libdispatch"))
Jason Molenda2fd83352014-02-05 05:44:54 +0000566 return extended_thread_sp;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567
568 bool stop_id_is_valid = true;
569 if (queue_item_sp->GetStopID() == 0)
570 stop_id_is_valid = false;
571
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000572 extended_thread_sp = std::make_shared<HistoryThread>(
573 *m_process, queue_item_sp->GetEnqueueingThreadID(),
574 queue_item_sp->GetEnqueueingBacktrace(), queue_item_sp->GetStopID(),
575 stop_id_is_valid);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000576 extended_thread_sp->SetExtendedBacktraceToken(
577 queue_item_sp->GetItemThatEnqueuedThis());
578 extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str());
579 extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID());
580 // extended_thread_sp->SetThreadName
581 // (queue_item_sp->GetThreadLabel().c_str());
582
583 return extended_thread_sp;
Jason Molenda2fd83352014-02-05 05:44:54 +0000584}
585
586/* Returns true if we were able to get the version / offset information
587 * out of libBacktraceRecording. false means we were unable to retrieve
588 * this; the queue_info_version field will be 0.
589 */
590
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() {
592 if (m_lib_backtrace_recording_info.queue_info_version != 0)
593 return true;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000594
Kate Stoneb9c1b512016-09-06 20:57:50 +0000595 addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
596 addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
597 addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
598 addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
599 Target &target = m_process->GetTarget();
Jason Molenda2fd83352014-02-05 05:44:54 +0000600
Kate Stoneb9c1b512016-09-06 20:57:50 +0000601 static ConstString introspection_dispatch_queue_info_version(
602 "__introspection_dispatch_queue_info_version");
603 SymbolContextList sc_list;
604 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
605 introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) >
606 0) {
607 SymbolContext sc;
608 sc_list.GetContextAtIndex(0, sc);
609 AddressRange addr_range;
610 sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
611 queue_info_version_address =
612 addr_range.GetBaseAddress().GetLoadAddress(&target);
613 }
614 sc_list.Clear();
Jason Molenda2fd83352014-02-05 05:44:54 +0000615
Kate Stoneb9c1b512016-09-06 20:57:50 +0000616 static ConstString introspection_dispatch_queue_info_data_offset(
617 "__introspection_dispatch_queue_info_data_offset");
618 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
619 introspection_dispatch_queue_info_data_offset, eSymbolTypeData,
620 sc_list) > 0) {
621 SymbolContext sc;
622 sc_list.GetContextAtIndex(0, sc);
623 AddressRange addr_range;
624 sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
625 queue_info_data_offset_address =
626 addr_range.GetBaseAddress().GetLoadAddress(&target);
627 }
628 sc_list.Clear();
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000629
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630 static ConstString introspection_dispatch_item_info_version(
631 "__introspection_dispatch_item_info_version");
632 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
633 introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) >
634 0) {
635 SymbolContext sc;
636 sc_list.GetContextAtIndex(0, sc);
637 AddressRange addr_range;
638 sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
639 item_info_version_address =
640 addr_range.GetBaseAddress().GetLoadAddress(&target);
641 }
642 sc_list.Clear();
Jason Molenda2fd83352014-02-05 05:44:54 +0000643
Kate Stoneb9c1b512016-09-06 20:57:50 +0000644 static ConstString introspection_dispatch_item_info_data_offset(
645 "__introspection_dispatch_item_info_data_offset");
646 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType(
647 introspection_dispatch_item_info_data_offset, eSymbolTypeData,
648 sc_list) > 0) {
649 SymbolContext sc;
650 sc_list.GetContextAtIndex(0, sc);
651 AddressRange addr_range;
652 sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range);
653 item_info_data_offset_address =
654 addr_range.GetBaseAddress().GetLoadAddress(&target);
655 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000656
Kate Stoneb9c1b512016-09-06 20:57:50 +0000657 if (queue_info_version_address != LLDB_INVALID_ADDRESS &&
658 queue_info_data_offset_address != LLDB_INVALID_ADDRESS &&
659 item_info_version_address != LLDB_INVALID_ADDRESS &&
660 item_info_data_offset_address != LLDB_INVALID_ADDRESS) {
Zachary Turner97206d52017-05-12 04:51:55 +0000661 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000662 m_lib_backtrace_recording_info.queue_info_version =
663 m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2,
664 0, error);
665 if (error.Success()) {
666 m_lib_backtrace_recording_info.queue_info_data_offset =
667 m_process->ReadUnsignedIntegerFromMemory(
668 queue_info_data_offset_address, 2, 0, error);
669 if (error.Success()) {
670 m_lib_backtrace_recording_info.item_info_version =
671 m_process->ReadUnsignedIntegerFromMemory(item_info_version_address,
672 2, 0, error);
673 if (error.Success()) {
674 m_lib_backtrace_recording_info.item_info_data_offset =
675 m_process->ReadUnsignedIntegerFromMemory(
676 item_info_data_offset_address, 2, 0, error);
677 if (!error.Success()) {
678 m_lib_backtrace_recording_info.queue_info_version = 0;
679 }
680 } else {
681 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000682 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683 } else {
684 m_lib_backtrace_recording_info.queue_info_version = 0;
685 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000686 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000687 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000688
Kate Stoneb9c1b512016-09-06 20:57:50 +0000689 return m_lib_backtrace_recording_info.queue_info_version != 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000690}
691
692const std::vector<ConstString> &
Kate Stoneb9c1b512016-09-06 20:57:50 +0000693SystemRuntimeMacOSX::GetExtendedBacktraceTypes() {
694 if (m_types.size() == 0) {
695 m_types.push_back(ConstString("libdispatch"));
696 // We could have pthread as another type in the future if we have a way of
697 // gathering that information & it's useful to distinguish between them.
698 }
699 return m_types;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000700}
701
Kate Stoneb9c1b512016-09-06 20:57:50 +0000702void SystemRuntimeMacOSX::PopulateQueueList(
703 lldb_private::QueueList &queue_list) {
704 if (BacktraceRecordingHeadersInitialized()) {
705 AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
706 ThreadSP cur_thread_sp(
707 m_process->GetThreadList().GetExpressionExecutionThread());
708 if (cur_thread_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000709 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000710 queue_info_pointer = m_get_queues_handler.GetCurrentQueues(
711 *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
712 m_page_to_free = LLDB_INVALID_ADDRESS;
713 m_page_to_free_size = 0;
714 if (error.Success()) {
Jason Molenda2fd83352014-02-05 05:44:54 +0000715
Kate Stoneb9c1b512016-09-06 20:57:50 +0000716 if (queue_info_pointer.count > 0 &&
717 queue_info_pointer.queues_buffer_size > 0 &&
718 queue_info_pointer.queues_buffer_ptr != 0 &&
719 queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) {
720 PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr,
721 queue_info_pointer.queues_buffer_size,
722 queue_info_pointer.count, queue_list);
Jason Molenda5e8dce42013-12-13 00:29:16 +0000723 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000724 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000725 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000726 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000727
Kate Stoneb9c1b512016-09-06 20:57:50 +0000728 // We either didn't have libBacktraceRecording (and need to create the queues
Adrian Prantl05097242018-04-30 16:49:04 +0000729 // list based on threads) or we did get the queues list from
730 // libBacktraceRecording but some special queues may not be included in its
731 // information. This is needed because libBacktraceRecording will only list
732 // queues with pending or running items by default - but the magic com.apple
733 // .main-thread queue on thread 1 is always around.
Jason Molendab9ffa982014-04-25 00:01:15 +0000734
Kate Stoneb9c1b512016-09-06 20:57:50 +0000735 for (ThreadSP thread_sp : m_process->Threads()) {
736 if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) {
737 if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) {
738 if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == NULL) {
739 QueueSP queue_sp(new Queue(m_process->shared_from_this(),
740 thread_sp->GetQueueID(),
741 thread_sp->GetQueueName()));
742 if (thread_sp->ThreadHasQueueInformation()) {
743 queue_sp->SetKind(thread_sp->GetQueueKind());
744 queue_sp->SetLibdispatchQueueAddress(
745 thread_sp->GetQueueLibdispatchQueueAddress());
746 queue_list.AddQueue(queue_sp);
747 } else {
748 queue_sp->SetKind(
749 GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress()));
750 queue_sp->SetLibdispatchQueueAddress(
751 thread_sp->GetQueueLibdispatchQueueAddress());
752 queue_list.AddQueue(queue_sp);
753 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000754 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000755 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000756 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000757 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000758}
759
Kate Stoneb9c1b512016-09-06 20:57:50 +0000760// Returns either an array of introspection_dispatch_item_info_ref's for the
Adrian Prantl05097242018-04-30 16:49:04 +0000761// pending items on a queue or an array introspection_dispatch_item_info_ref's
762// and code addresses for the pending items on a queue. The information about
763// each of these pending items then needs to be fetched individually by passing
764// the ref to libBacktraceRecording.
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000765
766SystemRuntimeMacOSX::PendingItemsForQueue
Kate Stoneb9c1b512016-09-06 20:57:50 +0000767SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) {
768 PendingItemsForQueue pending_item_refs;
769 AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
770 ThreadSP cur_thread_sp(
771 m_process->GetThreadList().GetExpressionExecutionThread());
772 if (cur_thread_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000773 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000774 pending_items_pointer = m_get_pending_items_handler.GetPendingItems(
775 *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size,
776 error);
Jason Molendae32cd192014-03-10 08:42:03 +0000777 m_page_to_free = LLDB_INVALID_ADDRESS;
778 m_page_to_free_size = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000779 if (error.Success()) {
780 if (pending_items_pointer.count > 0 &&
781 pending_items_pointer.items_buffer_size > 0 &&
782 pending_items_pointer.items_buffer_ptr != 0 &&
783 pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) {
784 DataBufferHeap data(pending_items_pointer.items_buffer_size, 0);
785 if (m_process->ReadMemory(
786 pending_items_pointer.items_buffer_ptr, data.GetBytes(),
787 pending_items_pointer.items_buffer_size, error)) {
788 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
789 m_process->GetByteOrder(),
790 m_process->GetAddressByteSize());
791
792 // We either have an array of
793 // void* item_ref
794 // (old style) or we have a structure returned which looks like
795 //
796 // struct introspection_dispatch_pending_item_info_s {
797 // void *item_ref;
798 // void *function_or_block;
799 // };
800 //
801 // struct introspection_dispatch_pending_items_array_s {
802 // uint32_t version;
803 // uint32_t size_of_item_info;
804 // introspection_dispatch_pending_item_info_s items[];
805 // }
806
807 offset_t offset = 0;
808 int i = 0;
809 uint32_t version = extractor.GetU32(&offset);
810 if (version == 1) {
811 pending_item_refs.new_style = true;
812 uint32_t item_size = extractor.GetU32(&offset);
813 uint32_t start_of_array_offset = offset;
814 while (offset < pending_items_pointer.items_buffer_size &&
815 static_cast<size_t>(i) < pending_items_pointer.count) {
816 offset = start_of_array_offset + (i * item_size);
817 ItemRefAndCodeAddress item;
818 item.item_ref = extractor.GetPointer(&offset);
819 item.code_address = extractor.GetPointer(&offset);
820 pending_item_refs.item_refs_and_code_addresses.push_back(item);
821 i++;
822 }
823 } else {
824 offset = 0;
825 pending_item_refs.new_style = false;
826 while (offset < pending_items_pointer.items_buffer_size &&
827 static_cast<size_t>(i) < pending_items_pointer.count) {
828 ItemRefAndCodeAddress item;
829 item.item_ref = extractor.GetPointer(&offset);
830 item.code_address = LLDB_INVALID_ADDRESS;
831 pending_item_refs.item_refs_and_code_addresses.push_back(item);
832 i++;
833 }
834 }
Jason Molendae32cd192014-03-10 08:42:03 +0000835 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000836 m_page_to_free = pending_items_pointer.items_buffer_ptr;
837 m_page_to_free_size = pending_items_pointer.items_buffer_size;
838 }
Jason Molendae32cd192014-03-10 08:42:03 +0000839 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000840 }
841 return pending_item_refs;
Jason Molendae32cd192014-03-10 08:42:03 +0000842}
843
Kate Stoneb9c1b512016-09-06 20:57:50 +0000844void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) {
845 if (BacktraceRecordingHeadersInitialized()) {
846 PendingItemsForQueue pending_item_refs =
847 GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress());
848 for (ItemRefAndCodeAddress pending_item :
849 pending_item_refs.item_refs_and_code_addresses) {
850 Address addr;
851 m_process->GetTarget().ResolveLoadAddress(pending_item.code_address,
852 addr);
853 QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(),
854 m_process->shared_from_this(),
855 pending_item.item_ref, addr));
856 queue->PushPendingQueueItem(queue_item_sp);
Jason Molenda2fd83352014-02-05 05:44:54 +0000857 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000858 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000859}
860
Kate Stoneb9c1b512016-09-06 20:57:50 +0000861void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item,
862 addr_t item_ref) {
863 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
Jason Molenda2fd83352014-02-05 05:44:54 +0000864
Kate Stoneb9c1b512016-09-06 20:57:50 +0000865 ThreadSP cur_thread_sp(
866 m_process->GetThreadList().GetExpressionExecutionThread());
Zachary Turner97206d52017-05-12 04:51:55 +0000867 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000868 ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref,
869 m_page_to_free, m_page_to_free_size,
870 error);
871 m_page_to_free = LLDB_INVALID_ADDRESS;
872 m_page_to_free_size = 0;
873 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS &&
874 ret.item_buffer_size > 0) {
875 DataBufferHeap data(ret.item_buffer_size, 0);
876 if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(),
877 ret.item_buffer_size, error) &&
878 error.Success()) {
879 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
880 m_process->GetByteOrder(),
881 m_process->GetAddressByteSize());
882 ItemInfo item = ExtractItemInfoFromBuffer(extractor);
883 queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this);
884 queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id);
885 queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum);
886 queue_item->SetStopID(item.stop_id);
887 queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack);
888 queue_item->SetThreadLabel(item.enqueuing_thread_label);
889 queue_item->SetQueueLabel(item.enqueuing_queue_label);
890 queue_item->SetTargetQueueLabel(item.target_queue_label);
891 }
892 m_page_to_free = ret.item_buffer_ptr;
893 m_page_to_free_size = ret.item_buffer_size;
894 }
895}
896
897void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR(
898 lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count,
899 lldb_private::QueueList &queue_list) {
Zachary Turner97206d52017-05-12 04:51:55 +0000900 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000901 DataBufferHeap data(queues_buffer_size, 0);
902 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME));
903 if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size,
904 error) == queues_buffer_size &&
905 error.Success()) {
906 // We've read the information out of inferior memory; free it on the next
907 // call we make
908 m_page_to_free = queues_buffer;
909 m_page_to_free_size = queues_buffer_size;
910
911 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
912 m_process->GetByteOrder(),
913 m_process->GetAddressByteSize());
Jason Molenda2fd83352014-02-05 05:44:54 +0000914 offset_t offset = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000915 uint64_t queues_read = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000916
Adrian Prantl05097242018-04-30 16:49:04 +0000917 // The information about the queues is stored in this format (v1): typedef
918 // struct introspection_dispatch_queue_info_s {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000919 // uint32_t offset_to_next;
920 // dispatch_queue_t queue;
921 // uint64_t serialnum; // queue's serialnum in the process, as
922 // provided by libdispatch
923 // uint32_t running_work_items_count;
924 // uint32_t pending_work_items_count;
925 //
926 // char data[]; // Starting here, we have variable-length data:
927 // // char queue_label[];
928 // } introspection_dispatch_queue_info_s;
Jason Molenda2fd83352014-02-05 05:44:54 +0000929
Kate Stoneb9c1b512016-09-06 20:57:50 +0000930 while (queues_read < count && offset < queues_buffer_size) {
931 offset_t start_of_this_item = offset;
932
933 uint32_t offset_to_next = extractor.GetU32(&offset);
934
935 offset += 4; // Skip over the 4 bytes of reserved space
936 addr_t queue = extractor.GetPointer(&offset);
937 uint64_t serialnum = extractor.GetU64(&offset);
938 uint32_t running_work_items_count = extractor.GetU32(&offset);
939 uint32_t pending_work_items_count = extractor.GetU32(&offset);
940
941 // Read the first field of the variable length data
942 offset = start_of_this_item +
943 m_lib_backtrace_recording_info.queue_info_data_offset;
944 const char *queue_label = extractor.GetCStr(&offset);
945 if (queue_label == NULL)
946 queue_label = "";
947
948 offset_t start_of_next_item = start_of_this_item + offset_to_next;
949 offset = start_of_next_item;
950
951 if (log)
952 log->Printf("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added "
953 "queue with dispatch_queue_t 0x%" PRIx64
954 ", serial number 0x%" PRIx64
955 ", running items %d, pending items %d, name '%s'",
956 queue, serialnum, running_work_items_count,
957 pending_work_items_count, queue_label);
958
959 QueueSP queue_sp(
960 new Queue(m_process->shared_from_this(), serialnum, queue_label));
961 queue_sp->SetNumRunningWorkItems(running_work_items_count);
962 queue_sp->SetNumPendingWorkItems(pending_work_items_count);
963 queue_sp->SetLibdispatchQueueAddress(queue);
964 queue_sp->SetKind(GetQueueKind(queue));
965 queue_list.AddQueue(queue_sp);
966 queues_read++;
Jason Molenda2fd83352014-02-05 05:44:54 +0000967 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000969}
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000970
Kate Stoneb9c1b512016-09-06 20:57:50 +0000971SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer(
972 lldb_private::DataExtractor &extractor) {
973 ItemInfo item;
974
975 offset_t offset = 0;
976
977 item.item_that_enqueued_this = extractor.GetPointer(&offset);
978 item.function_or_block = extractor.GetPointer(&offset);
979 item.enqueuing_thread_id = extractor.GetU64(&offset);
980 item.enqueuing_queue_serialnum = extractor.GetU64(&offset);
981 item.target_queue_serialnum = extractor.GetU64(&offset);
982 item.enqueuing_callstack_frame_count = extractor.GetU32(&offset);
983 item.stop_id = extractor.GetU32(&offset);
984
985 offset = m_lib_backtrace_recording_info.item_info_data_offset;
986
987 for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) {
988 item.enqueuing_callstack.push_back(extractor.GetPointer(&offset));
989 }
990 item.enqueuing_thread_label = extractor.GetCStr(&offset);
991 item.enqueuing_queue_label = extractor.GetCStr(&offset);
992 item.target_queue_label = extractor.GetCStr(&offset);
993
994 return item;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000995}
996
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997void SystemRuntimeMacOSX::Initialize() {
998 PluginManager::RegisterPlugin(GetPluginNameStatic(),
999 GetPluginDescriptionStatic(), CreateInstance);
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001000}
1001
Kate Stoneb9c1b512016-09-06 20:57:50 +00001002void SystemRuntimeMacOSX::Terminate() {
1003 PluginManager::UnregisterPlugin(CreateInstance);
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001004}
1005
Kate Stoneb9c1b512016-09-06 20:57:50 +00001006lldb_private::ConstString SystemRuntimeMacOSX::GetPluginNameStatic() {
1007 static ConstString g_name("systemruntime-macosx");
1008 return g_name;
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001009}
1010
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011const char *SystemRuntimeMacOSX::GetPluginDescriptionStatic() {
1012 return "System runtime plugin for Mac OS X native libraries.";
1013}
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001014
1015//------------------------------------------------------------------
1016// PluginInterface protocol
1017//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001018lldb_private::ConstString SystemRuntimeMacOSX::GetPluginName() {
1019 return GetPluginNameStatic();
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001020}
1021
Kate Stoneb9c1b512016-09-06 20:57:50 +00001022uint32_t SystemRuntimeMacOSX::GetPluginVersion() { return 1; }