blob: 9ec36b383af3fc20b1b553f61fcc5476ed34f84b [file] [log] [blame]
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11#include "lldb/Breakpoint/StoppointCallbackContext.h"
12#include "lldb/Core/Log.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/ModuleSpec.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/DataBufferHeap.h"
18#include "lldb/Core/Section.h"
Jason Molenda705b1802014-06-13 02:37:02 +000019#include "lldb/Core/StreamString.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000020#include "lldb/Host/FileSpec.h"
Zachary Turner88c6b622015-03-03 18:34:26 +000021#include "lldb/Symbol/ClangASTContext.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000022#include "lldb/Symbol/ObjectFile.h"
23#include "lldb/Symbol/SymbolContext.h"
24#include "Plugins/Process/Utility/HistoryThread.h"
Jason Molenda5e8dce42013-12-13 00:29:16 +000025#include "lldb/Target/Queue.h"
26#include "lldb/Target/QueueList.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000027#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000029#include "lldb/Target/Process.h"
Jason Molenda59ac67e2014-09-12 00:09:04 +000030#include "lldb/Utility/ProcessStructReader.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000031
Jason Molendaa7b5afa2013-11-15 00:17:32 +000032#include "SystemRuntimeMacOSX.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37//----------------------------------------------------------------------
38// Create an instance of this class. This function is filled into
39// the plugin info class that gets handed out by the plugin factory and
40// allows the lldb to instantiate an instance of this class.
41//----------------------------------------------------------------------
42SystemRuntime *
43SystemRuntimeMacOSX::CreateInstance (Process* process)
44{
45 bool create = false;
46 if (!create)
47 {
48 create = true;
49 Module* exe_module = process->GetTarget().GetExecutableModulePointer();
50 if (exe_module)
51 {
52 ObjectFile *object_file = exe_module->GetObjectFile();
53 if (object_file)
54 {
55 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
56 }
57 }
58
59 if (create)
60 {
61 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
62 switch (triple_ref.getOS())
63 {
64 case llvm::Triple::Darwin:
65 case llvm::Triple::MacOSX:
66 case llvm::Triple::IOS:
Jason Molendaa814f702015-11-05 23:03:44 +000067 case llvm::Triple::TvOS:
68 case llvm::Triple::WatchOS:
Jason Molendaa7b5afa2013-11-15 00:17:32 +000069 create = triple_ref.getVendor() == llvm::Triple::Apple;
70 break;
71 default:
72 create = false;
73 break;
74 }
75 }
76 }
77
78 if (create)
79 return new SystemRuntimeMacOSX (process);
80 return NULL;
81}
82
83//----------------------------------------------------------------------
84// Constructor
85//----------------------------------------------------------------------
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000086SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process)
87 : SystemRuntime(process),
88 m_break_id(LLDB_INVALID_BREAK_ID),
89 m_mutex(),
90 m_get_queues_handler(process),
91 m_get_pending_items_handler(process),
92 m_get_item_info_handler(process),
93 m_get_thread_item_info_handler(process),
94 m_page_to_free(LLDB_INVALID_ADDRESS),
95 m_page_to_free_size(0),
96 m_lib_backtrace_recording_info(),
97 m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS),
98 m_libdispatch_offsets(),
99 m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS),
100 m_libpthread_offsets(),
101 m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS),
102 m_libdispatch_tsd_indexes(),
103 m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS),
104 m_libdispatch_voucher_offsets()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000105{
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000106}
107
108//----------------------------------------------------------------------
109// Destructor
110//----------------------------------------------------------------------
111SystemRuntimeMacOSX::~SystemRuntimeMacOSX()
112{
113 Clear (true);
114}
115
Jason Molenda2fd83352014-02-05 05:44:54 +0000116void
117SystemRuntimeMacOSX::Detach ()
118{
119 m_get_queues_handler.Detach();
120 m_get_pending_items_handler.Detach();
121 m_get_item_info_handler.Detach();
122 m_get_thread_item_info_handler.Detach();
123}
124
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000125//----------------------------------------------------------------------
126// Clear out the state of this class.
127//----------------------------------------------------------------------
128void
129SystemRuntimeMacOSX::Clear (bool clear_process)
130{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000131 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000132
133 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
134 m_process->ClearBreakpointSiteByID(m_break_id);
135
136 if (clear_process)
137 m_process = NULL;
138 m_break_id = LLDB_INVALID_BREAK_ID;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000139}
140
141
Jason Molenda2fd83352014-02-05 05:44:54 +0000142std::string
143SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress (addr_t dispatch_qaddr)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000144{
Jason Molenda2fd83352014-02-05 05:44:54 +0000145 std::string dispatch_queue_name;
146 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
147 return "";
148
149 ReadLibdispatchOffsets ();
150 if (m_libdispatch_offsets.IsValid ())
151 {
152 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a thread -
153 // deref it to get the address of the dispatch_queue_t structure for this thread's
154 // queue.
155 Error error;
156 addr_t dispatch_queue_addr = m_process->ReadPointerFromMemory (dispatch_qaddr, error);
157 if (error.Success())
158 {
159 if (m_libdispatch_offsets.dqo_version >= 4)
160 {
161 // libdispatch versions 4+, pointer to dispatch name is in the
162 // queue structure.
163 addr_t pointer_to_label_address = dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
164 addr_t label_addr = m_process->ReadPointerFromMemory (pointer_to_label_address, error);
165 if (error.Success())
166 {
167 m_process->ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
168 }
169 }
170 else
171 {
172 // libdispatch versions 1-3, dispatch name is a fixed width char array
173 // in the queue structure.
174 addr_t label_addr = dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
175 dispatch_queue_name.resize (m_libdispatch_offsets.dqo_label_size, '\0');
176 size_t bytes_read = m_process->ReadMemory (label_addr, &dispatch_queue_name[0], m_libdispatch_offsets.dqo_label_size, error);
177 if (bytes_read < m_libdispatch_offsets.dqo_label_size)
178 dispatch_queue_name.erase (bytes_read);
179 }
180 }
181 }
182 return dispatch_queue_name;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000183}
184
Jason Molendaaac16e02014-03-13 02:54:54 +0000185lldb::addr_t
186SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress (addr_t dispatch_qaddr)
187{
188 addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
189 Error error;
190 libdispatch_queue_t_address = m_process->ReadPointerFromMemory (dispatch_qaddr, error);
191 if (!error.Success())
192 {
193 libdispatch_queue_t_address = LLDB_INVALID_ADDRESS;
194 }
195 return libdispatch_queue_t_address;
196}
197
198lldb::QueueKind
199SystemRuntimeMacOSX::GetQueueKind (addr_t dispatch_queue_addr)
200{
201 if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0)
202 return eQueueKindUnknown;
203
204 QueueKind kind = eQueueKindUnknown;
205 ReadLibdispatchOffsets ();
206 if (m_libdispatch_offsets.IsValid () && m_libdispatch_offsets.dqo_version >= 4)
207 {
208 Error error;
209 uint64_t width = m_process->ReadUnsignedIntegerFromMemory (dispatch_queue_addr + m_libdispatch_offsets.dqo_width, m_libdispatch_offsets.dqo_width_size, 0, error);
210 if (error.Success())
211 {
212 if (width == 1)
213 {
214 kind = eQueueKindSerial;
215 }
216 if (width > 1)
217 {
218 kind = eQueueKindConcurrent;
219 }
220 }
221 }
222 return kind;
223}
224
Jason Molenda705b1802014-06-13 02:37:02 +0000225void
226SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints (lldb_private::StructuredData::ObjectSP dict_sp)
227{
228 StructuredData::Dictionary *dict = dict_sp->GetAsDictionary();
229 if (dict)
230 {
231 ReadLibpthreadOffsets();
232 if (m_libpthread_offsets.IsValid())
233 {
234 dict->AddIntegerItem ("plo_pthread_tsd_base_offset", m_libpthread_offsets.plo_pthread_tsd_base_offset);
235 dict->AddIntegerItem ("plo_pthread_tsd_base_address_offset", m_libpthread_offsets.plo_pthread_tsd_base_address_offset);
236 dict->AddIntegerItem ("plo_pthread_tsd_entry_size", m_libpthread_offsets.plo_pthread_tsd_entry_size);
237 }
238
239 ReadLibdispatchTSDIndexes ();
240 if (m_libdispatch_tsd_indexes.IsValid())
241 {
242 dict->AddIntegerItem ("dti_queue_index", m_libdispatch_tsd_indexes.dti_queue_index);
243 dict->AddIntegerItem ("dti_voucher_index", m_libdispatch_tsd_indexes.dti_voucher_index);
244 dict->AddIntegerItem ("dti_qos_class_index", m_libdispatch_tsd_indexes.dti_qos_class_index);
245 }
246 }
247}
248
Jason Molendab4892cd2014-05-13 22:02:48 +0000249bool
250SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread (ThreadSP thread_sp)
251{
252 if (thread_sp && thread_sp->GetStackFrameCount() > 0 && thread_sp->GetFrameWithConcreteFrameIndex(0))
253 {
254 const SymbolContext sym_ctx (thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext (eSymbolContextSymbol));
255 static ConstString g_select_symbol ("__select");
256 if (sym_ctx.GetFunctionName() == g_select_symbol)
257 {
258 return false;
259 }
260 }
261 return true;
262}
263
Jason Molenda2fd83352014-02-05 05:44:54 +0000264lldb::queue_id_t
265SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress (lldb::addr_t dispatch_qaddr)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000266{
Jason Molenda2fd83352014-02-05 05:44:54 +0000267 queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
268
269 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
270 return queue_id;
271
272 ReadLibdispatchOffsets ();
273 if (m_libdispatch_offsets.IsValid ())
274 {
275 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a thread -
276 // deref it to get the address of the dispatch_queue_t structure for this thread's
277 // queue.
278 Error error;
279 uint64_t dispatch_queue_addr = m_process->ReadPointerFromMemory (dispatch_qaddr, error);
280 if (error.Success())
281 {
282 addr_t serialnum_address = dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;
283 queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory (serialnum_address, m_libdispatch_offsets.dqo_serialnum_size, LLDB_INVALID_QUEUE_ID, error);
284 if (error.Success())
285 {
286 queue_id = serialnum;
287 }
288 }
289 }
290
291 return queue_id;
292}
293
294
295void
296SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress ()
297{
298 if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)
299 return;
300
301 static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
302 const Symbol *dispatch_queue_offsets_symbol = NULL;
303
304 // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 ("Snow Leopard")
305 ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
306 ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
307 if (module_sp)
308 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
309
310 // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and later
311 if (dispatch_queue_offsets_symbol == NULL)
312 {
313 ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
314 module_sp = m_process->GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
315 if (module_sp)
316 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
317 }
318 if (dispatch_queue_offsets_symbol)
Greg Clayton358cf1e2015-06-25 21:46:34 +0000319 m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget());
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000320}
321
322void
Jason Molenda2fd83352014-02-05 05:44:54 +0000323SystemRuntimeMacOSX::ReadLibdispatchOffsets ()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000324{
Jason Molenda2fd83352014-02-05 05:44:54 +0000325 if (m_libdispatch_offsets.IsValid())
326 return;
327
328 ReadLibdispatchOffsetsAddress ();
329
330 uint8_t memory_buffer[sizeof (struct LibdispatchOffsets)];
331 DataExtractor data (memory_buffer,
332 sizeof(memory_buffer),
333 m_process->GetByteOrder(),
334 m_process->GetAddressByteSize());
335
336 Error error;
337 if (m_process->ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(memory_buffer), error) == sizeof(memory_buffer))
338 {
339 lldb::offset_t data_offset = 0;
340
341 // The struct LibdispatchOffsets is a series of uint16_t's - extract them all
342 // in one big go.
343 data.GetU16 (&data_offset, &m_libdispatch_offsets.dqo_version, sizeof (struct LibdispatchOffsets) / sizeof (uint16_t));
344 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000345}
346
Jason Molenda705b1802014-06-13 02:37:02 +0000347void
348SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress ()
349{
350 if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)
351 return;
352
353 static ConstString g_libpthread_layout_offsets_symbol_name ("pthread_layout_offsets");
354 const Symbol *libpthread_layout_offsets_symbol = NULL;
355
356 ModuleSpec libpthread_module_spec (FileSpec("libsystem_pthread.dylib", false));
357 ModuleSP module_sp (m_process->GetTarget().GetImages().FindFirstModule (libpthread_module_spec));
358 if (module_sp)
359 {
360 libpthread_layout_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType
361 (g_libpthread_layout_offsets_symbol_name, eSymbolTypeData);
362 if (libpthread_layout_offsets_symbol)
363 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000364 m_libpthread_layout_offsets_addr = libpthread_layout_offsets_symbol->GetLoadAddress(&m_process->GetTarget());
Jason Molenda705b1802014-06-13 02:37:02 +0000365 }
366 }
367}
368
369void
370SystemRuntimeMacOSX::ReadLibpthreadOffsets ()
371{
372 if (m_libpthread_offsets.IsValid())
373 return;
374
375 ReadLibpthreadOffsetsAddress ();
376
377 if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS)
378 {
379 uint8_t memory_buffer[sizeof (struct LibpthreadOffsets)];
380 DataExtractor data (memory_buffer,
381 sizeof(memory_buffer),
382 m_process->GetByteOrder(),
383 m_process->GetAddressByteSize());
384 Error error;
385 if (m_process->ReadMemory (m_libpthread_layout_offsets_addr, memory_buffer, sizeof(memory_buffer), error) == sizeof(memory_buffer))
386 {
387 lldb::offset_t data_offset = 0;
388
389 // The struct LibpthreadOffsets is a series of uint16_t's - extract them all
390 // in one big go.
391 data.GetU16 (&data_offset, &m_libpthread_offsets.plo_version, sizeof (struct LibpthreadOffsets) / sizeof (uint16_t));
392 }
393 }
394}
395
396void
397SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress ()
398{
399 if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
400 return;
401
402 static ConstString g_libdispatch_tsd_indexes_symbol_name ("dispatch_tsd_indexes");
403 const Symbol *libdispatch_tsd_indexes_symbol = NULL;
404
405 ModuleSpec libpthread_module_spec (FileSpec("libdispatch.dylib", false));
406 ModuleSP module_sp (m_process->GetTarget().GetImages().FindFirstModule (libpthread_module_spec));
407 if (module_sp)
408 {
409 libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType
410 (g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData);
411 if (libdispatch_tsd_indexes_symbol)
412 {
Greg Clayton358cf1e2015-06-25 21:46:34 +0000413 m_dispatch_tsd_indexes_addr = libdispatch_tsd_indexes_symbol->GetLoadAddress(&m_process->GetTarget());
Jason Molenda705b1802014-06-13 02:37:02 +0000414 }
415 }
416}
417
418void
419SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes ()
420{
421 if (m_libdispatch_tsd_indexes.IsValid())
422 return;
423
424 ReadLibdispatchTSDIndexesAddress ();
425
426 if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
427 {
Jason Molenda59ac67e2014-09-12 00:09:04 +0000428
429 // We don't need to check the version number right now, it will be at least 2, but
430 // keep this code around to fetch just the version # for the future where we need
431 // to fetch alternate versions of the struct.
432# if 0
Jason Molenda705b1802014-06-13 02:37:02 +0000433 uint16_t dti_version = 2;
Jason Molenda59ac67e2014-09-12 00:09:04 +0000434 Address dti_struct_addr;
435 if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr))
Jason Molenda705b1802014-06-13 02:37:02 +0000436 {
437 Error error;
438 uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);
439 if (error.Success() && dti_version != UINT16_MAX)
440 {
441 dti_version = version;
442 }
443 }
Jason Molenda59ac67e2014-09-12 00:09:04 +0000444#endif
Jason Molenda705b1802014-06-13 02:37:02 +0000445
Jason Molenda59ac67e2014-09-12 00:09:04 +0000446 ClangASTContext *ast_ctx = m_process->GetTarget().GetScratchClangASTContext();
447 if (ast_ctx->getASTContext() && m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS)
Jason Molenda705b1802014-06-13 02:37:02 +0000448 {
Greg Clayton56939cb2015-09-17 22:23:34 +0000449 CompilerType uint16 = ast_ctx->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 16);
Greg Claytona1e5dc82015-08-11 22:53:00 +0000450 CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct, lldb::eLanguageTypeC);
Greg Claytond8d4a572015-08-11 21:38:15 +0000451
452 ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s);
453 ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_version", uint16, lldb::eAccessPublic, 0);
454 ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_queue_index", uint16, lldb::eAccessPublic, 0);
455 ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_voucher_index", uint16, lldb::eAccessPublic, 0);
456 ClangASTContext::AddFieldToRecordType (dispatch_tsd_indexes_s, "dti_qos_class_index", uint16, lldb::eAccessPublic, 0);
457 ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s);
Jason Molenda59ac67e2014-09-12 00:09:04 +0000458
459 ProcessStructReader struct_reader (m_process, m_dispatch_tsd_indexes_addr, dispatch_tsd_indexes_s);
460
461 m_libdispatch_tsd_indexes.dti_version = struct_reader.GetField<uint16_t>(ConstString("dti_version"));
462 m_libdispatch_tsd_indexes.dti_queue_index = struct_reader.GetField<uint16_t>(ConstString("dti_queue_index"));
463 m_libdispatch_tsd_indexes.dti_voucher_index = struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index"));
464 m_libdispatch_tsd_indexes.dti_qos_class_index = struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index"));
Jason Molenda705b1802014-06-13 02:37:02 +0000465 }
466 }
467}
468
Jason Molenda2fd83352014-02-05 05:44:54 +0000469
470ThreadSP
471SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type)
472{
473 ThreadSP originating_thread_sp;
474 if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch"))
475 {
476 Error error;
477
478 // real_thread is either an actual, live thread (in which case we need to call into
479 // libBacktraceRecording to find its originator) or it is an extended backtrace itself,
480 // in which case we get the token from it and call into libBacktraceRecording to find
481 // the originator of that token.
482
483 if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS)
484 {
485 originating_thread_sp = GetExtendedBacktraceFromItemRef (real_thread->GetExtendedBacktraceToken());
486 }
487 else
488 {
Jim Ingham8d94ba02016-03-12 02:45:34 +0000489 ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread());
Jason Molendada276f92014-02-11 00:36:18 +0000490 AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret = m_get_thread_item_info_handler.GetThreadItemInfo (*cur_thread_sp.get(), real_thread->GetID(), m_page_to_free, m_page_to_free_size, error);
Jason Molenda2a6c2522014-02-15 00:20:40 +0000491 m_page_to_free = LLDB_INVALID_ADDRESS;
492 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000493 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
494 {
495 DataBufferHeap data (ret.item_buffer_size, 0);
496 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
497 {
498 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
499 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
500 bool stop_id_is_valid = true;
501 if (item.stop_id == 0)
502 stop_id_is_valid = false;
503 originating_thread_sp.reset (new HistoryThread (*m_process,
504 item.enqueuing_thread_id,
505 item.enqueuing_callstack,
506 item.stop_id,
507 stop_id_is_valid));
508 originating_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
509 originating_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
510 originating_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
511// originating_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
512 }
Jason Molendada276f92014-02-11 00:36:18 +0000513 m_page_to_free = ret.item_buffer_ptr;
514 m_page_to_free_size = ret.item_buffer_size;
Jason Molenda2fd83352014-02-05 05:44:54 +0000515 }
516 }
517 }
518 return originating_thread_sp;
519}
520
521ThreadSP
522SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref)
523{
524 ThreadSP return_thread_sp;
525
526 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
Jim Ingham8d94ba02016-03-12 02:45:34 +0000527 ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread());
Jason Molenda2fd83352014-02-05 05:44:54 +0000528 Error error;
529 ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
Jason Molenda2a6c2522014-02-15 00:20:40 +0000530 m_page_to_free = LLDB_INVALID_ADDRESS;
531 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000532 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
533 {
534 DataBufferHeap data (ret.item_buffer_size, 0);
535 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
536 {
537 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
538 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
539 bool stop_id_is_valid = true;
540 if (item.stop_id == 0)
541 stop_id_is_valid = false;
542 return_thread_sp.reset (new HistoryThread (*m_process,
543 item.enqueuing_thread_id,
544 item.enqueuing_callstack,
545 item.stop_id,
546 stop_id_is_valid));
547 return_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
548 return_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
549 return_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
550// return_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
551
Jason Molendada276f92014-02-11 00:36:18 +0000552 m_page_to_free = ret.item_buffer_ptr;
553 m_page_to_free_size = ret.item_buffer_size;
Jason Molenda2fd83352014-02-05 05:44:54 +0000554 }
555 }
556 return return_thread_sp;
557}
558
559ThreadSP
560SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem (QueueItemSP queue_item_sp, ConstString type)
561{
562 ThreadSP extended_thread_sp;
563 if (type != ConstString("libdispatch"))
564 return extended_thread_sp;
565
566 bool stop_id_is_valid = true;
567 if (queue_item_sp->GetStopID() == 0)
568 stop_id_is_valid = false;
569
570 extended_thread_sp.reset (new HistoryThread (*m_process,
571 queue_item_sp->GetEnqueueingThreadID(),
572 queue_item_sp->GetEnqueueingBacktrace(),
573 queue_item_sp->GetStopID(),
574 stop_id_is_valid));
575 extended_thread_sp->SetExtendedBacktraceToken (queue_item_sp->GetItemThatEnqueuedThis());
576 extended_thread_sp->SetQueueName (queue_item_sp->GetQueueLabel().c_str());
577 extended_thread_sp->SetQueueID (queue_item_sp->GetEnqueueingQueueID());
578// extended_thread_sp->SetThreadName (queue_item_sp->GetThreadLabel().c_str());
579
580 return extended_thread_sp;
581}
582
583/* Returns true if we were able to get the version / offset information
584 * out of libBacktraceRecording. false means we were unable to retrieve
585 * this; the queue_info_version field will be 0.
586 */
587
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000588bool
Jason Molenda2fd83352014-02-05 05:44:54 +0000589SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized ()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000590{
Jason Molenda2fd83352014-02-05 05:44:54 +0000591 if (m_lib_backtrace_recording_info.queue_info_version != 0)
592 return true;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000593
Jason Molenda2fd83352014-02-05 05:44:54 +0000594 addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
595 addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
596 addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
597 addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
598 Target &target = m_process->GetTarget();
599
600
601 static ConstString introspection_dispatch_queue_info_version ("__introspection_dispatch_queue_info_version");
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000602 SymbolContextList sc_list;
Jason Molenda2fd83352014-02-05 05:44:54 +0000603 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > 0)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000604 {
605 SymbolContext sc;
606 sc_list.GetContextAtIndex (0, sc);
607 AddressRange addr_range;
608 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
Jason Molenda2fd83352014-02-05 05:44:54 +0000609 queue_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
610 }
611 sc_list.Clear();
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000612
Jason Molenda2fd83352014-02-05 05:44:54 +0000613 static ConstString introspection_dispatch_queue_info_data_offset ("__introspection_dispatch_queue_info_data_offset");
614 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list) > 0)
615 {
616 SymbolContext sc;
617 sc_list.GetContextAtIndex (0, sc);
618 AddressRange addr_range;
619 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
620 queue_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
621 }
622 sc_list.Clear();
623
624 static ConstString introspection_dispatch_item_info_version ("__introspection_dispatch_item_info_version");
625 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > 0)
626 {
627 SymbolContext sc;
628 sc_list.GetContextAtIndex (0, sc);
629 AddressRange addr_range;
630 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
631 item_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
632 }
633 sc_list.Clear();
634
635 static ConstString introspection_dispatch_item_info_data_offset ("__introspection_dispatch_item_info_data_offset");
636 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list) > 0)
637 {
638 SymbolContext sc;
639 sc_list.GetContextAtIndex (0, sc);
640 AddressRange addr_range;
641 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
642 item_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
643 }
644
645 if (queue_info_version_address != LLDB_INVALID_ADDRESS
646 && queue_info_data_offset_address != LLDB_INVALID_ADDRESS
647 && item_info_version_address != LLDB_INVALID_ADDRESS
648 && item_info_data_offset_address != LLDB_INVALID_ADDRESS)
649 {
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000650 Error error;
Jason Molenda2fd83352014-02-05 05:44:54 +0000651 m_lib_backtrace_recording_info.queue_info_version = m_process->ReadUnsignedIntegerFromMemory (queue_info_version_address, 2, 0, error);
652 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000653 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000654 m_lib_backtrace_recording_info.queue_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (queue_info_data_offset_address, 2, 0, error);
655 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000656 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000657 m_lib_backtrace_recording_info.item_info_version = m_process->ReadUnsignedIntegerFromMemory (item_info_version_address, 2, 0, error);
658 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000659 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000660 m_lib_backtrace_recording_info.item_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (item_info_data_offset_address, 2, 0, error);
661 if (!error.Success())
Jason Molendaa6e91302013-11-19 05:44:41 +0000662 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000663 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa6e91302013-11-19 05:44:41 +0000664 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000665 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000666 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000667 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000668 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000669 }
670 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000671 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000672 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000673 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000674 }
675 }
676 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000677
Jason Molenda2fd83352014-02-05 05:44:54 +0000678 return m_lib_backtrace_recording_info.queue_info_version != 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000679}
680
681const std::vector<ConstString> &
682SystemRuntimeMacOSX::GetExtendedBacktraceTypes ()
683{
684 if (m_types.size () == 0)
685 {
686 m_types.push_back(ConstString("libdispatch"));
Jason Molenda2fd83352014-02-05 05:44:54 +0000687 // We could have pthread as another type in the future if we have a way of
688 // gathering that information & it's useful to distinguish between them.
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000689 }
690 return m_types;
691}
692
693void
Jason Molenda5e8dce42013-12-13 00:29:16 +0000694SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
695{
Jason Molendab9ffa982014-04-25 00:01:15 +0000696 if (BacktraceRecordingHeadersInitialized())
Jason Molenda2fd83352014-02-05 05:44:54 +0000697 {
698 AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
Jim Ingham8d94ba02016-03-12 02:45:34 +0000699 ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread());
Jason Molenda2fd83352014-02-05 05:44:54 +0000700 if (cur_thread_sp)
701 {
702 Error error;
703 queue_info_pointer = m_get_queues_handler.GetCurrentQueues (*cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
Jason Molenda2a6c2522014-02-15 00:20:40 +0000704 m_page_to_free = LLDB_INVALID_ADDRESS;
705 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000706 if (error.Success())
707 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000708
709 if (queue_info_pointer.count > 0
710 && queue_info_pointer.queues_buffer_size > 0
711 && queue_info_pointer.queues_buffer_ptr != 0
712 && queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS)
713 {
714 PopulateQueuesUsingLibBTR (queue_info_pointer.queues_buffer_ptr, queue_info_pointer.queues_buffer_size, queue_info_pointer.count, queue_list);
715 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000716 }
717 }
718 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000719
720 // We either didn't have libBacktraceRecording (and need to create the queues list based on threads)
721 // or we did get the queues list from libBacktraceRecording but some special queues may not be
722 // included in its information. This is needed because libBacktraceRecording
723 // will only list queues with pending or running items by default - but the magic com.apple.main-thread
724 // queue on thread 1 is always around.
725
726 for (ThreadSP thread_sp : m_process->Threads())
727 {
Jason Molenda77f89352016-01-12 07:09:16 +0000728 if (thread_sp->GetAssociatedWithLibdispatchQueue () != eLazyBoolNo)
Jason Molendab9ffa982014-04-25 00:01:15 +0000729 {
Jason Molenda77f89352016-01-12 07:09:16 +0000730 if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
Jason Molendab9ffa982014-04-25 00:01:15 +0000731 {
Jason Molenda77f89352016-01-12 07:09:16 +0000732 if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
733 {
734 QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
735 if (thread_sp->ThreadHasQueueInformation ())
736 {
737 queue_sp->SetKind (thread_sp->GetQueueKind ());
738 queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
739 queue_list.AddQueue (queue_sp);
740 }
741 else
742 {
743 queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
744 queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
745 queue_list.AddQueue (queue_sp);
746 }
747 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000748 }
749 }
750 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000751}
752
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000753// Returns either an array of introspection_dispatch_item_info_ref's for the pending items on
754// a queue or an array introspection_dispatch_item_info_ref's and code addresses for the
755// pending items on a queue. The information about each of these pending items then needs to
756// be fetched individually by passing the ref to libBacktraceRecording.
757
758SystemRuntimeMacOSX::PendingItemsForQueue
759SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
760{
761 PendingItemsForQueue pending_item_refs;
762 AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
Jim Ingham8d94ba02016-03-12 02:45:34 +0000763 ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread());
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000764 if (cur_thread_sp)
765 {
766 Error error;
767 pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error);
768 m_page_to_free = LLDB_INVALID_ADDRESS;
769 m_page_to_free_size = 0;
770 if (error.Success())
771 {
772 if (pending_items_pointer.count > 0
773 && pending_items_pointer.items_buffer_size > 0
774 && pending_items_pointer.items_buffer_ptr != 0
775 && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS)
776 {
777 DataBufferHeap data (pending_items_pointer.items_buffer_size, 0);
778 if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error))
779 {
780 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
781
782 // We either have an array of
783 // void* item_ref
784 // (old style) or we have a structure returned which looks like
785 //
786 // struct introspection_dispatch_pending_item_info_s {
787 // void *item_ref;
788 // void *function_or_block;
789 // };
790 //
791 // struct introspection_dispatch_pending_items_array_s {
792 // uint32_t version;
793 // uint32_t size_of_item_info;
794 // introspection_dispatch_pending_item_info_s items[];
795 // }
796
797 offset_t offset = 0;
798 int i = 0;
799 uint32_t version = extractor.GetU32(&offset);
800 if (version == 1)
801 {
802 pending_item_refs.new_style = true;
803 uint32_t item_size = extractor.GetU32(&offset);
804 uint32_t start_of_array_offset = offset;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +0000805 while (offset < pending_items_pointer.items_buffer_size &&
806 static_cast<size_t>(i) < pending_items_pointer.count)
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000807 {
808 offset = start_of_array_offset + (i * item_size);
809 ItemRefAndCodeAddress item;
810 item.item_ref = extractor.GetPointer (&offset);
811 item.code_address = extractor.GetPointer (&offset);
812 pending_item_refs.item_refs_and_code_addresses.push_back (item);
813 i++;
814 }
815 }
816 else
817 {
818 offset = 0;
819 pending_item_refs.new_style = false;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +0000820 while (offset < pending_items_pointer.items_buffer_size &&
821 static_cast<size_t>(i) < pending_items_pointer.count)
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000822 {
823 ItemRefAndCodeAddress item;
824 item.item_ref = extractor.GetPointer (&offset);
825 item.code_address = LLDB_INVALID_ADDRESS;
826 pending_item_refs.item_refs_and_code_addresses.push_back (item);
827 i++;
828 }
829 }
830 }
831 m_page_to_free = pending_items_pointer.items_buffer_ptr;
832 m_page_to_free_size = pending_items_pointer.items_buffer_size;
833 }
834 }
835 }
836 return pending_item_refs;
837}
838
839
840
Jason Molenda2fd83352014-02-05 05:44:54 +0000841void
842SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
843{
844 if (BacktraceRecordingHeadersInitialized())
845 {
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000846 PendingItemsForQueue pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
847 for (ItemRefAndCodeAddress pending_item : pending_item_refs.item_refs_and_code_addresses)
Jason Molenda2fd83352014-02-05 05:44:54 +0000848 {
Jason Molendae32cd192014-03-10 08:42:03 +0000849 Address addr;
850 m_process->GetTarget().ResolveLoadAddress (pending_item.code_address, addr);
851 QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this(), m_process->shared_from_this(), pending_item.item_ref, addr));
852 queue->PushPendingQueueItem (queue_item_sp);
Jason Molenda2fd83352014-02-05 05:44:54 +0000853 }
854 }
855}
856
Jason Molendae32cd192014-03-10 08:42:03 +0000857void
858SystemRuntimeMacOSX::CompleteQueueItem (QueueItem *queue_item, addr_t item_ref)
859{
860 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
861
Jim Ingham8d94ba02016-03-12 02:45:34 +0000862 ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread());
Jason Molendae32cd192014-03-10 08:42:03 +0000863 Error error;
864 ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
865 m_page_to_free = LLDB_INVALID_ADDRESS;
866 m_page_to_free_size = 0;
867 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
868 {
869 DataBufferHeap data (ret.item_buffer_size, 0);
870 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
871 {
872 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
873 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
874 queue_item->SetItemThatEnqueuedThis (item.item_that_enqueued_this);
875 queue_item->SetEnqueueingThreadID (item.enqueuing_thread_id);
876 queue_item->SetEnqueueingQueueID (item.enqueuing_queue_serialnum);
877 queue_item->SetStopID (item.stop_id);
878 queue_item->SetEnqueueingBacktrace (item.enqueuing_callstack);
879 queue_item->SetThreadLabel (item.enqueuing_thread_label);
880 queue_item->SetQueueLabel (item.enqueuing_queue_label);
881 queue_item->SetTargetQueueLabel (item.target_queue_label);
882 }
883 m_page_to_free = ret.item_buffer_ptr;
884 m_page_to_free_size = ret.item_buffer_size;
885 }
886}
887
Jason Molenda2fd83352014-02-05 05:44:54 +0000888void
889SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
890 uint64_t count, lldb_private::QueueList &queue_list)
891{
892 Error error;
893 DataBufferHeap data (queues_buffer_size, 0);
Jason Molendad84f6062014-02-26 22:27:09 +0000894 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
Jason Molenda2fd83352014-02-05 05:44:54 +0000895 if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
896 {
897 // We've read the information out of inferior memory; free it on the next call we make
898 m_page_to_free = queues_buffer;
899 m_page_to_free_size = queues_buffer_size;
900
901 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
902 offset_t offset = 0;
903 uint64_t queues_read = 0;
904
905 // The information about the queues is stored in this format (v1):
906 // typedef struct introspection_dispatch_queue_info_s {
907 // uint32_t offset_to_next;
908 // dispatch_queue_t queue;
909 // uint64_t serialnum; // queue's serialnum in the process, as provided by libdispatch
910 // uint32_t running_work_items_count;
911 // uint32_t pending_work_items_count;
912 //
913 // char data[]; // Starting here, we have variable-length data:
914 // // char queue_label[];
915 // } introspection_dispatch_queue_info_s;
916
917 while (queues_read < count && offset < queues_buffer_size)
918 {
919 offset_t start_of_this_item = offset;
920
921 uint32_t offset_to_next = extractor.GetU32 (&offset);
Jason Molendad84f6062014-02-26 22:27:09 +0000922
923 offset += 4; // Skip over the 4 bytes of reserved space
Jason Molenda2fd83352014-02-05 05:44:54 +0000924 addr_t queue = extractor.GetPointer (&offset);
925 uint64_t serialnum = extractor.GetU64 (&offset);
926 uint32_t running_work_items_count = extractor.GetU32 (&offset);
927 uint32_t pending_work_items_count = extractor.GetU32 (&offset);
928
929 // Read the first field of the variable length data
930 offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
931 const char *queue_label = extractor.GetCStr (&offset);
932 if (queue_label == NULL)
933 queue_label = "";
934
935 offset_t start_of_next_item = start_of_this_item + offset_to_next;
936 offset = start_of_next_item;
937
Jason Molendad84f6062014-02-26 22:27:09 +0000938 if (log)
939 log->Printf ("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added queue with dispatch_queue_t 0x%" PRIx64 ", serial number 0x%" PRIx64 ", running items %d, pending items %d, name '%s'", queue, serialnum, running_work_items_count, pending_work_items_count, queue_label);
940
Jason Molenda2fd83352014-02-05 05:44:54 +0000941 QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
942 queue_sp->SetNumRunningWorkItems (running_work_items_count);
943 queue_sp->SetNumPendingWorkItems (pending_work_items_count);
944 queue_sp->SetLibdispatchQueueAddress (queue);
Jason Molendaaac16e02014-03-13 02:54:54 +0000945 queue_sp->SetKind (GetQueueKind (queue));
Jason Molenda2fd83352014-02-05 05:44:54 +0000946 queue_list.AddQueue (queue_sp);
947 queues_read++;
948 }
949 }
950}
951
952SystemRuntimeMacOSX::ItemInfo
953SystemRuntimeMacOSX::ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor)
954{
955 ItemInfo item;
956
957 offset_t offset = 0;
958
959 item.item_that_enqueued_this = extractor.GetPointer (&offset);
960 item.function_or_block = extractor.GetPointer (&offset);
961 item.enqueuing_thread_id = extractor.GetU64 (&offset);
962 item.enqueuing_queue_serialnum = extractor.GetU64 (&offset);
963 item.target_queue_serialnum = extractor.GetU64 (&offset);
964 item.enqueuing_callstack_frame_count = extractor.GetU32 (&offset);
965 item.stop_id = extractor.GetU32 (&offset);
966
967 offset = m_lib_backtrace_recording_info.item_info_data_offset;
968
969 for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++)
970 {
971 item.enqueuing_callstack.push_back (extractor.GetPointer (&offset));
972 }
973 item.enqueuing_thread_label = extractor.GetCStr (&offset);
974 item.enqueuing_queue_label = extractor.GetCStr (&offset);
975 item.target_queue_label = extractor.GetCStr (&offset);
976
977 return item;
978}
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000979
980void
981SystemRuntimeMacOSX::Initialize()
982{
983 PluginManager::RegisterPlugin (GetPluginNameStatic(),
984 GetPluginDescriptionStatic(),
985 CreateInstance);
986}
987
988void
989SystemRuntimeMacOSX::Terminate()
990{
991 PluginManager::UnregisterPlugin (CreateInstance);
992}
993
994
995lldb_private::ConstString
996SystemRuntimeMacOSX::GetPluginNameStatic()
997{
998 static ConstString g_name("systemruntime-macosx");
999 return g_name;
1000}
1001
1002const char *
1003SystemRuntimeMacOSX::GetPluginDescriptionStatic()
1004{
1005 return "System runtime plugin for Mac OS X native libraries.";
1006}
1007
1008
1009//------------------------------------------------------------------
1010// PluginInterface protocol
1011//------------------------------------------------------------------
1012lldb_private::ConstString
1013SystemRuntimeMacOSX::GetPluginName()
1014{
1015 return GetPluginNameStatic();
1016}
1017
1018uint32_t
1019SystemRuntimeMacOSX::GetPluginVersion()
1020{
1021 return 1;
1022}