blob: 9b18eadbf1dc8261ef4a80fbbca86626187758b1 [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/Expression/ClangFunction.h"
21#include "lldb/Expression/ClangUtilityFunction.h"
22#include "lldb/Host/FileSpec.h"
Zachary Turner88c6b622015-03-03 18:34:26 +000023#include "lldb/Symbol/ClangASTContext.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000024#include "lldb/Symbol/ObjectFile.h"
25#include "lldb/Symbol/SymbolContext.h"
26#include "Plugins/Process/Utility/HistoryThread.h"
Jason Molenda5e8dce42013-12-13 00:29:16 +000027#include "lldb/Target/Queue.h"
28#include "lldb/Target/QueueList.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000029#include "lldb/Target/Target.h"
30#include "lldb/Target/Thread.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000031#include "lldb/Target/Process.h"
Jason Molenda59ac67e2014-09-12 00:09:04 +000032#include "lldb/Utility/ProcessStructReader.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000033
Jason Molendaa7b5afa2013-11-15 00:17:32 +000034#include "SystemRuntimeMacOSX.h"
35
36using namespace lldb;
37using namespace lldb_private;
38
39//----------------------------------------------------------------------
40// Create an instance of this class. This function is filled into
41// the plugin info class that gets handed out by the plugin factory and
42// allows the lldb to instantiate an instance of this class.
43//----------------------------------------------------------------------
44SystemRuntime *
45SystemRuntimeMacOSX::CreateInstance (Process* process)
46{
47 bool create = false;
48 if (!create)
49 {
50 create = true;
51 Module* exe_module = process->GetTarget().GetExecutableModulePointer();
52 if (exe_module)
53 {
54 ObjectFile *object_file = exe_module->GetObjectFile();
55 if (object_file)
56 {
57 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
58 }
59 }
60
61 if (create)
62 {
63 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
64 switch (triple_ref.getOS())
65 {
66 case llvm::Triple::Darwin:
67 case llvm::Triple::MacOSX:
68 case llvm::Triple::IOS:
69 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//----------------------------------------------------------------------
86SystemRuntimeMacOSX::SystemRuntimeMacOSX (Process* process) :
87 SystemRuntime(process),
88 m_break_id(LLDB_INVALID_BREAK_ID),
Jason Molenda2fd83352014-02-05 05:44:54 +000089 m_mutex(Mutex::eMutexTypeRecursive),
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),
Jason Molenda705b1802014-06-13 02:37:02 +000098 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{
131 Mutex::Locker locker(m_mutex);
132
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)
319 m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().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 {
364 m_libpthread_layout_offsets_addr = libpthread_layout_offsets_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget());
365 }
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 {
413 m_dispatch_tsd_indexes_addr = libdispatch_tsd_indexes_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget());
414 }
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 {
Jason Molenda59ac67e2014-09-12 00:09:04 +0000449 ClangASTType uint16 = ast_ctx->GetIntTypeFromBitSize(16, false);
450 ClangASTType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct, lldb::eLanguageTypeC);
451 dispatch_tsd_indexes_s.StartTagDeclarationDefinition();
452 dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_version", uint16, lldb::eAccessPublic, 0);
453 dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_queue_index", uint16, lldb::eAccessPublic, 0);
454 dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_voucher_index", uint16, lldb::eAccessPublic, 0);
455 dispatch_tsd_indexes_s.AddFieldToRecordType ("dti_qos_class_index", uint16, lldb::eAccessPublic, 0);
456 dispatch_tsd_indexes_s.CompleteTagDeclarationDefinition();
457
458 ProcessStructReader struct_reader (m_process, m_dispatch_tsd_indexes_addr, dispatch_tsd_indexes_s);
459
460 m_libdispatch_tsd_indexes.dti_version = struct_reader.GetField<uint16_t>(ConstString("dti_version"));
461 m_libdispatch_tsd_indexes.dti_queue_index = struct_reader.GetField<uint16_t>(ConstString("dti_queue_index"));
462 m_libdispatch_tsd_indexes.dti_voucher_index = struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index"));
463 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 +0000464 }
465 }
466}
467
Jason Molenda2fd83352014-02-05 05:44:54 +0000468
469ThreadSP
470SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type)
471{
472 ThreadSP originating_thread_sp;
473 if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch"))
474 {
475 Error error;
476
477 // real_thread is either an actual, live thread (in which case we need to call into
478 // libBacktraceRecording to find its originator) or it is an extended backtrace itself,
479 // in which case we get the token from it and call into libBacktraceRecording to find
480 // the originator of that token.
481
482 if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS)
483 {
484 originating_thread_sp = GetExtendedBacktraceFromItemRef (real_thread->GetExtendedBacktraceToken());
485 }
486 else
487 {
Jason Molendada276f92014-02-11 00:36:18 +0000488 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
489 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 +0000490 m_page_to_free = LLDB_INVALID_ADDRESS;
491 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000492 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
493 {
494 DataBufferHeap data (ret.item_buffer_size, 0);
495 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
496 {
497 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
498 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
499 bool stop_id_is_valid = true;
500 if (item.stop_id == 0)
501 stop_id_is_valid = false;
502 originating_thread_sp.reset (new HistoryThread (*m_process,
503 item.enqueuing_thread_id,
504 item.enqueuing_callstack,
505 item.stop_id,
506 stop_id_is_valid));
507 originating_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
508 originating_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
509 originating_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
510// originating_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
511 }
Jason Molendada276f92014-02-11 00:36:18 +0000512 m_page_to_free = ret.item_buffer_ptr;
513 m_page_to_free_size = ret.item_buffer_size;
Jason Molenda2fd83352014-02-05 05:44:54 +0000514 }
515 }
516 }
517 return originating_thread_sp;
518}
519
520ThreadSP
521SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref)
522{
523 ThreadSP return_thread_sp;
524
525 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
526 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
527 Error error;
528 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 +0000529 m_page_to_free = LLDB_INVALID_ADDRESS;
530 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000531 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
532 {
533 DataBufferHeap data (ret.item_buffer_size, 0);
534 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
535 {
536 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
537 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
538 bool stop_id_is_valid = true;
539 if (item.stop_id == 0)
540 stop_id_is_valid = false;
541 return_thread_sp.reset (new HistoryThread (*m_process,
542 item.enqueuing_thread_id,
543 item.enqueuing_callstack,
544 item.stop_id,
545 stop_id_is_valid));
546 return_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
547 return_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
548 return_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
549// return_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
550
Jason Molendada276f92014-02-11 00:36:18 +0000551 m_page_to_free = ret.item_buffer_ptr;
552 m_page_to_free_size = ret.item_buffer_size;
Jason Molenda2fd83352014-02-05 05:44:54 +0000553 }
554 }
555 return return_thread_sp;
556}
557
558ThreadSP
559SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem (QueueItemSP queue_item_sp, ConstString type)
560{
561 ThreadSP extended_thread_sp;
562 if (type != ConstString("libdispatch"))
563 return extended_thread_sp;
564
565 bool stop_id_is_valid = true;
566 if (queue_item_sp->GetStopID() == 0)
567 stop_id_is_valid = false;
568
569 extended_thread_sp.reset (new HistoryThread (*m_process,
570 queue_item_sp->GetEnqueueingThreadID(),
571 queue_item_sp->GetEnqueueingBacktrace(),
572 queue_item_sp->GetStopID(),
573 stop_id_is_valid));
574 extended_thread_sp->SetExtendedBacktraceToken (queue_item_sp->GetItemThatEnqueuedThis());
575 extended_thread_sp->SetQueueName (queue_item_sp->GetQueueLabel().c_str());
576 extended_thread_sp->SetQueueID (queue_item_sp->GetEnqueueingQueueID());
577// extended_thread_sp->SetThreadName (queue_item_sp->GetThreadLabel().c_str());
578
579 return extended_thread_sp;
580}
581
582/* Returns true if we were able to get the version / offset information
583 * out of libBacktraceRecording. false means we were unable to retrieve
584 * this; the queue_info_version field will be 0.
585 */
586
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000587bool
Jason Molenda2fd83352014-02-05 05:44:54 +0000588SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized ()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000589{
Jason Molenda2fd83352014-02-05 05:44:54 +0000590 if (m_lib_backtrace_recording_info.queue_info_version != 0)
591 return true;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000592
Jason Molenda2fd83352014-02-05 05:44:54 +0000593 addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
594 addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
595 addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
596 addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
597 Target &target = m_process->GetTarget();
598
599
600 static ConstString introspection_dispatch_queue_info_version ("__introspection_dispatch_queue_info_version");
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000601 SymbolContextList sc_list;
Jason Molenda2fd83352014-02-05 05:44:54 +0000602 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > 0)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000603 {
604 SymbolContext sc;
605 sc_list.GetContextAtIndex (0, sc);
606 AddressRange addr_range;
607 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
Jason Molenda2fd83352014-02-05 05:44:54 +0000608 queue_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
609 }
610 sc_list.Clear();
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000611
Jason Molenda2fd83352014-02-05 05:44:54 +0000612 static ConstString introspection_dispatch_queue_info_data_offset ("__introspection_dispatch_queue_info_data_offset");
613 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list) > 0)
614 {
615 SymbolContext sc;
616 sc_list.GetContextAtIndex (0, sc);
617 AddressRange addr_range;
618 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
619 queue_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
620 }
621 sc_list.Clear();
622
623 static ConstString introspection_dispatch_item_info_version ("__introspection_dispatch_item_info_version");
624 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > 0)
625 {
626 SymbolContext sc;
627 sc_list.GetContextAtIndex (0, sc);
628 AddressRange addr_range;
629 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
630 item_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
631 }
632 sc_list.Clear();
633
634 static ConstString introspection_dispatch_item_info_data_offset ("__introspection_dispatch_item_info_data_offset");
635 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list) > 0)
636 {
637 SymbolContext sc;
638 sc_list.GetContextAtIndex (0, sc);
639 AddressRange addr_range;
640 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
641 item_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
642 }
643
644 if (queue_info_version_address != LLDB_INVALID_ADDRESS
645 && queue_info_data_offset_address != LLDB_INVALID_ADDRESS
646 && item_info_version_address != LLDB_INVALID_ADDRESS
647 && item_info_data_offset_address != LLDB_INVALID_ADDRESS)
648 {
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000649 Error error;
Jason Molenda2fd83352014-02-05 05:44:54 +0000650 m_lib_backtrace_recording_info.queue_info_version = m_process->ReadUnsignedIntegerFromMemory (queue_info_version_address, 2, 0, error);
651 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000652 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000653 m_lib_backtrace_recording_info.queue_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (queue_info_data_offset_address, 2, 0, error);
654 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000655 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000656 m_lib_backtrace_recording_info.item_info_version = m_process->ReadUnsignedIntegerFromMemory (item_info_version_address, 2, 0, error);
657 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000658 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000659 m_lib_backtrace_recording_info.item_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (item_info_data_offset_address, 2, 0, error);
660 if (!error.Success())
Jason Molendaa6e91302013-11-19 05:44:41 +0000661 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000662 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa6e91302013-11-19 05:44:41 +0000663 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000664 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000665 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000666 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000667 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000668 }
669 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000670 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000671 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000672 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000673 }
674 }
675 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000676
Jason Molenda2fd83352014-02-05 05:44:54 +0000677 return m_lib_backtrace_recording_info.queue_info_version != 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000678}
679
680const std::vector<ConstString> &
681SystemRuntimeMacOSX::GetExtendedBacktraceTypes ()
682{
683 if (m_types.size () == 0)
684 {
685 m_types.push_back(ConstString("libdispatch"));
Jason Molenda2fd83352014-02-05 05:44:54 +0000686 // We could have pthread as another type in the future if we have a way of
687 // gathering that information & it's useful to distinguish between them.
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000688 }
689 return m_types;
690}
691
692void
Jason Molenda5e8dce42013-12-13 00:29:16 +0000693SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
694{
Jason Molendab9ffa982014-04-25 00:01:15 +0000695 if (BacktraceRecordingHeadersInitialized())
Jason Molenda2fd83352014-02-05 05:44:54 +0000696 {
697 AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
698 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
699 if (cur_thread_sp)
700 {
701 Error error;
702 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 +0000703 m_page_to_free = LLDB_INVALID_ADDRESS;
704 m_page_to_free_size = 0;
Jason Molenda2fd83352014-02-05 05:44:54 +0000705 if (error.Success())
706 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000707
708 if (queue_info_pointer.count > 0
709 && queue_info_pointer.queues_buffer_size > 0
710 && queue_info_pointer.queues_buffer_ptr != 0
711 && queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS)
712 {
713 PopulateQueuesUsingLibBTR (queue_info_pointer.queues_buffer_ptr, queue_info_pointer.queues_buffer_size, queue_info_pointer.count, queue_list);
714 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000715 }
716 }
717 }
Jason Molendab9ffa982014-04-25 00:01:15 +0000718
719 // We either didn't have libBacktraceRecording (and need to create the queues list based on threads)
720 // or we did get the queues list from libBacktraceRecording but some special queues may not be
721 // included in its information. This is needed because libBacktraceRecording
722 // will only list queues with pending or running items by default - but the magic com.apple.main-thread
723 // queue on thread 1 is always around.
724
725 for (ThreadSP thread_sp : m_process->Threads())
726 {
727 if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
728 {
729 if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
730 {
731 QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
732 queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
733 queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
734 queue_list.AddQueue (queue_sp);
735 }
736 }
737 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000738}
739
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000740// Returns either an array of introspection_dispatch_item_info_ref's for the pending items on
741// a queue or an array introspection_dispatch_item_info_ref's and code addresses for the
742// pending items on a queue. The information about each of these pending items then needs to
743// be fetched individually by passing the ref to libBacktraceRecording.
744
745SystemRuntimeMacOSX::PendingItemsForQueue
746SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
747{
748 PendingItemsForQueue pending_item_refs;
749 AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
750 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
751 if (cur_thread_sp)
752 {
753 Error error;
754 pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error);
755 m_page_to_free = LLDB_INVALID_ADDRESS;
756 m_page_to_free_size = 0;
757 if (error.Success())
758 {
759 if (pending_items_pointer.count > 0
760 && pending_items_pointer.items_buffer_size > 0
761 && pending_items_pointer.items_buffer_ptr != 0
762 && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS)
763 {
764 DataBufferHeap data (pending_items_pointer.items_buffer_size, 0);
765 if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error))
766 {
767 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
768
769 // We either have an array of
770 // void* item_ref
771 // (old style) or we have a structure returned which looks like
772 //
773 // struct introspection_dispatch_pending_item_info_s {
774 // void *item_ref;
775 // void *function_or_block;
776 // };
777 //
778 // struct introspection_dispatch_pending_items_array_s {
779 // uint32_t version;
780 // uint32_t size_of_item_info;
781 // introspection_dispatch_pending_item_info_s items[];
782 // }
783
784 offset_t offset = 0;
785 int i = 0;
786 uint32_t version = extractor.GetU32(&offset);
787 if (version == 1)
788 {
789 pending_item_refs.new_style = true;
790 uint32_t item_size = extractor.GetU32(&offset);
791 uint32_t start_of_array_offset = offset;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +0000792 while (offset < pending_items_pointer.items_buffer_size &&
793 static_cast<size_t>(i) < pending_items_pointer.count)
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000794 {
795 offset = start_of_array_offset + (i * item_size);
796 ItemRefAndCodeAddress item;
797 item.item_ref = extractor.GetPointer (&offset);
798 item.code_address = extractor.GetPointer (&offset);
799 pending_item_refs.item_refs_and_code_addresses.push_back (item);
800 i++;
801 }
802 }
803 else
804 {
805 offset = 0;
806 pending_item_refs.new_style = false;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +0000807 while (offset < pending_items_pointer.items_buffer_size &&
808 static_cast<size_t>(i) < pending_items_pointer.count)
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000809 {
810 ItemRefAndCodeAddress item;
811 item.item_ref = extractor.GetPointer (&offset);
812 item.code_address = LLDB_INVALID_ADDRESS;
813 pending_item_refs.item_refs_and_code_addresses.push_back (item);
814 i++;
815 }
816 }
817 }
818 m_page_to_free = pending_items_pointer.items_buffer_ptr;
819 m_page_to_free_size = pending_items_pointer.items_buffer_size;
820 }
821 }
822 }
823 return pending_item_refs;
824}
825
826
827
Jason Molenda2fd83352014-02-05 05:44:54 +0000828void
829SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
830{
831 if (BacktraceRecordingHeadersInitialized())
832 {
Jason Molenda37e9b5a2014-03-09 21:17:08 +0000833 PendingItemsForQueue pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
834 for (ItemRefAndCodeAddress pending_item : pending_item_refs.item_refs_and_code_addresses)
Jason Molenda2fd83352014-02-05 05:44:54 +0000835 {
Jason Molendae32cd192014-03-10 08:42:03 +0000836 Address addr;
837 m_process->GetTarget().ResolveLoadAddress (pending_item.code_address, addr);
838 QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this(), m_process->shared_from_this(), pending_item.item_ref, addr));
839 queue->PushPendingQueueItem (queue_item_sp);
Jason Molenda2fd83352014-02-05 05:44:54 +0000840 }
841 }
842}
843
Jason Molendae32cd192014-03-10 08:42:03 +0000844void
845SystemRuntimeMacOSX::CompleteQueueItem (QueueItem *queue_item, addr_t item_ref)
846{
847 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
848
849 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
850 Error error;
851 ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
852 m_page_to_free = LLDB_INVALID_ADDRESS;
853 m_page_to_free_size = 0;
854 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
855 {
856 DataBufferHeap data (ret.item_buffer_size, 0);
857 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
858 {
859 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
860 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
861 queue_item->SetItemThatEnqueuedThis (item.item_that_enqueued_this);
862 queue_item->SetEnqueueingThreadID (item.enqueuing_thread_id);
863 queue_item->SetEnqueueingQueueID (item.enqueuing_queue_serialnum);
864 queue_item->SetStopID (item.stop_id);
865 queue_item->SetEnqueueingBacktrace (item.enqueuing_callstack);
866 queue_item->SetThreadLabel (item.enqueuing_thread_label);
867 queue_item->SetQueueLabel (item.enqueuing_queue_label);
868 queue_item->SetTargetQueueLabel (item.target_queue_label);
869 }
870 m_page_to_free = ret.item_buffer_ptr;
871 m_page_to_free_size = ret.item_buffer_size;
872 }
873}
874
Jason Molenda2fd83352014-02-05 05:44:54 +0000875void
876SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
877 uint64_t count, lldb_private::QueueList &queue_list)
878{
879 Error error;
880 DataBufferHeap data (queues_buffer_size, 0);
Jason Molendad84f6062014-02-26 22:27:09 +0000881 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
Jason Molenda2fd83352014-02-05 05:44:54 +0000882 if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
883 {
884 // We've read the information out of inferior memory; free it on the next call we make
885 m_page_to_free = queues_buffer;
886 m_page_to_free_size = queues_buffer_size;
887
888 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
889 offset_t offset = 0;
890 uint64_t queues_read = 0;
891
892 // The information about the queues is stored in this format (v1):
893 // typedef struct introspection_dispatch_queue_info_s {
894 // uint32_t offset_to_next;
895 // dispatch_queue_t queue;
896 // uint64_t serialnum; // queue's serialnum in the process, as provided by libdispatch
897 // uint32_t running_work_items_count;
898 // uint32_t pending_work_items_count;
899 //
900 // char data[]; // Starting here, we have variable-length data:
901 // // char queue_label[];
902 // } introspection_dispatch_queue_info_s;
903
904 while (queues_read < count && offset < queues_buffer_size)
905 {
906 offset_t start_of_this_item = offset;
907
908 uint32_t offset_to_next = extractor.GetU32 (&offset);
Jason Molendad84f6062014-02-26 22:27:09 +0000909
910 offset += 4; // Skip over the 4 bytes of reserved space
Jason Molenda2fd83352014-02-05 05:44:54 +0000911 addr_t queue = extractor.GetPointer (&offset);
912 uint64_t serialnum = extractor.GetU64 (&offset);
913 uint32_t running_work_items_count = extractor.GetU32 (&offset);
914 uint32_t pending_work_items_count = extractor.GetU32 (&offset);
915
916 // Read the first field of the variable length data
917 offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
918 const char *queue_label = extractor.GetCStr (&offset);
919 if (queue_label == NULL)
920 queue_label = "";
921
922 offset_t start_of_next_item = start_of_this_item + offset_to_next;
923 offset = start_of_next_item;
924
Jason Molendad84f6062014-02-26 22:27:09 +0000925 if (log)
926 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);
927
Jason Molenda2fd83352014-02-05 05:44:54 +0000928 QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
929 queue_sp->SetNumRunningWorkItems (running_work_items_count);
930 queue_sp->SetNumPendingWorkItems (pending_work_items_count);
931 queue_sp->SetLibdispatchQueueAddress (queue);
Jason Molendaaac16e02014-03-13 02:54:54 +0000932 queue_sp->SetKind (GetQueueKind (queue));
Jason Molenda2fd83352014-02-05 05:44:54 +0000933 queue_list.AddQueue (queue_sp);
934 queues_read++;
935 }
936 }
937}
938
939SystemRuntimeMacOSX::ItemInfo
940SystemRuntimeMacOSX::ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor)
941{
942 ItemInfo item;
943
944 offset_t offset = 0;
945
946 item.item_that_enqueued_this = extractor.GetPointer (&offset);
947 item.function_or_block = extractor.GetPointer (&offset);
948 item.enqueuing_thread_id = extractor.GetU64 (&offset);
949 item.enqueuing_queue_serialnum = extractor.GetU64 (&offset);
950 item.target_queue_serialnum = extractor.GetU64 (&offset);
951 item.enqueuing_callstack_frame_count = extractor.GetU32 (&offset);
952 item.stop_id = extractor.GetU32 (&offset);
953
954 offset = m_lib_backtrace_recording_info.item_info_data_offset;
955
956 for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++)
957 {
958 item.enqueuing_callstack.push_back (extractor.GetPointer (&offset));
959 }
960 item.enqueuing_thread_label = extractor.GetCStr (&offset);
961 item.enqueuing_queue_label = extractor.GetCStr (&offset);
962 item.target_queue_label = extractor.GetCStr (&offset);
963
964 return item;
965}
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000966
967void
968SystemRuntimeMacOSX::Initialize()
969{
970 PluginManager::RegisterPlugin (GetPluginNameStatic(),
971 GetPluginDescriptionStatic(),
972 CreateInstance);
973}
974
975void
976SystemRuntimeMacOSX::Terminate()
977{
978 PluginManager::UnregisterPlugin (CreateInstance);
979}
980
981
982lldb_private::ConstString
983SystemRuntimeMacOSX::GetPluginNameStatic()
984{
985 static ConstString g_name("systemruntime-macosx");
986 return g_name;
987}
988
989const char *
990SystemRuntimeMacOSX::GetPluginDescriptionStatic()
991{
992 return "System runtime plugin for Mac OS X native libraries.";
993}
994
995
996//------------------------------------------------------------------
997// PluginInterface protocol
998//------------------------------------------------------------------
999lldb_private::ConstString
1000SystemRuntimeMacOSX::GetPluginName()
1001{
1002 return GetPluginNameStatic();
1003}
1004
1005uint32_t
1006SystemRuntimeMacOSX::GetPluginVersion()
1007{
1008 return 1;
1009}