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