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/Expression/ClangFunction.h"
21 #include "lldb/Expression/ClangUtilityFunction.h"
22 #include "lldb/Host/FileSpec.h"
23 #include "lldb/Symbol/ObjectFile.h"
24 #include "lldb/Symbol/SymbolContext.h"
25 #include "Plugins/Process/Utility/HistoryThread.h"
26 #include "lldb/Target/Queue.h"
27 #include "lldb/Target/QueueList.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Target/Process.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->GetAddress().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->GetAddress().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->GetAddress().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         size_t maximum_tsd_indexes_struct_size;
427         Address dti_struct_addr;
428         uint16_t dti_version = 2;
429         if (m_process->GetTarget().ResolveLoadAddress(m_dispatch_tsd_indexes_addr, dti_struct_addr))
430         {
431             Error error;
432             uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error);
433             if (error.Success() && dti_version != UINT16_MAX)
434             {
435                 dti_version = version;
436             }
437         }
438         if (dti_version == 1)
439         {
440             if (m_process->GetAddressByteSize() == 4)
441             {
442                 maximum_tsd_indexes_struct_size = 4 + 4 + 4 + 4;
443             }
444             else
445             {
446                 maximum_tsd_indexes_struct_size = 8 + 8 + 8 + 8;
447             }
448         }
449         else
450         {
451             maximum_tsd_indexes_struct_size = 2 + 2 + 2 + 2;
452         }
453 
454         uint8_t memory_buffer[maximum_tsd_indexes_struct_size];
455         DataExtractor data (memory_buffer,
456                             sizeof(memory_buffer),
457                             m_process->GetByteOrder(),
458                             m_process->GetAddressByteSize());
459         Error error;
460         if (m_process->ReadMemory (m_dispatch_tsd_indexes_addr, memory_buffer, sizeof(memory_buffer), error) == sizeof(memory_buffer))
461         {
462             lldb::offset_t offset = 0;
463 
464             if (dti_version == 1)
465             {
466                 m_libdispatch_tsd_indexes.dti_version = data.GetU16 (&offset);
467                 // word alignment to next item
468                 if (m_process->GetAddressByteSize() == 4)
469                 {
470                     offset += 2;
471                 }
472                 else
473                 {
474                     offset += 6;
475                 }
476                 m_libdispatch_tsd_indexes.dti_queue_index = data.GetPointer (&offset);
477                 m_libdispatch_tsd_indexes.dti_voucher_index = data.GetPointer (&offset);
478                 m_libdispatch_tsd_indexes.dti_qos_class_index = data.GetPointer (&offset);
479             }
480             else
481             {
482                 m_libdispatch_tsd_indexes.dti_version = data.GetU16 (&offset);
483                 m_libdispatch_tsd_indexes.dti_queue_index = data.GetU16 (&offset);
484                 m_libdispatch_tsd_indexes.dti_voucher_index = data.GetU16 (&offset);
485                 m_libdispatch_tsd_indexes.dti_qos_class_index = data.GetU16 (&offset);
486             }
487         }
488     }
489 }
490 
491 
492 ThreadSP
493 SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type)
494 {
495     ThreadSP originating_thread_sp;
496     if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch"))
497     {
498         Error error;
499 
500         // real_thread is either an actual, live thread (in which case we need to call into
501         // libBacktraceRecording to find its originator) or it is an extended backtrace itself,
502         // in which case we get the token from it and call into libBacktraceRecording to find
503         // the originator of that token.
504 
505         if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS)
506         {
507             originating_thread_sp = GetExtendedBacktraceFromItemRef (real_thread->GetExtendedBacktraceToken());
508         }
509         else
510         {
511             ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
512             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);
513             m_page_to_free = LLDB_INVALID_ADDRESS;
514             m_page_to_free_size = 0;
515             if (ret.item_buffer_ptr != 0 &&  ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
516             {
517                 DataBufferHeap data (ret.item_buffer_size, 0);
518                 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
519                 {
520                     DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
521                     ItemInfo item = ExtractItemInfoFromBuffer (extractor);
522                     bool stop_id_is_valid = true;
523                     if (item.stop_id == 0)
524                         stop_id_is_valid = false;
525                     originating_thread_sp.reset (new HistoryThread (*m_process,
526                                                                     item.enqueuing_thread_id,
527                                                                     item.enqueuing_callstack,
528                                                                     item.stop_id,
529                                                                     stop_id_is_valid));
530                     originating_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
531                     originating_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
532                     originating_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
533 //                    originating_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
534                 }
535                 m_page_to_free = ret.item_buffer_ptr;
536                 m_page_to_free_size = ret.item_buffer_size;
537             }
538         }
539     }
540     return originating_thread_sp;
541 }
542 
543 ThreadSP
544 SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref)
545 {
546     ThreadSP return_thread_sp;
547 
548     AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
549     ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
550     Error error;
551     ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
552     m_page_to_free = LLDB_INVALID_ADDRESS;
553     m_page_to_free_size = 0;
554     if (ret.item_buffer_ptr != 0 &&  ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
555     {
556         DataBufferHeap data (ret.item_buffer_size, 0);
557         if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
558         {
559             DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
560             ItemInfo item = ExtractItemInfoFromBuffer (extractor);
561             bool stop_id_is_valid = true;
562             if (item.stop_id == 0)
563                 stop_id_is_valid = false;
564             return_thread_sp.reset (new HistoryThread (*m_process,
565                                                             item.enqueuing_thread_id,
566                                                             item.enqueuing_callstack,
567                                                             item.stop_id,
568                                                             stop_id_is_valid));
569             return_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
570             return_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
571             return_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
572 //            return_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
573 
574             m_page_to_free = ret.item_buffer_ptr;
575             m_page_to_free_size = ret.item_buffer_size;
576         }
577     }
578     return return_thread_sp;
579 }
580 
581 ThreadSP
582 SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem (QueueItemSP queue_item_sp, ConstString type)
583 {
584     ThreadSP extended_thread_sp;
585     if (type != ConstString("libdispatch"))
586         return extended_thread_sp;
587 
588     bool stop_id_is_valid = true;
589     if (queue_item_sp->GetStopID() == 0)
590         stop_id_is_valid = false;
591 
592     extended_thread_sp.reset (new HistoryThread (*m_process,
593                                                  queue_item_sp->GetEnqueueingThreadID(),
594                                                  queue_item_sp->GetEnqueueingBacktrace(),
595                                                  queue_item_sp->GetStopID(),
596                                                  stop_id_is_valid));
597     extended_thread_sp->SetExtendedBacktraceToken (queue_item_sp->GetItemThatEnqueuedThis());
598     extended_thread_sp->SetQueueName (queue_item_sp->GetQueueLabel().c_str());
599     extended_thread_sp->SetQueueID (queue_item_sp->GetEnqueueingQueueID());
600 //    extended_thread_sp->SetThreadName (queue_item_sp->GetThreadLabel().c_str());
601 
602     return extended_thread_sp;
603 }
604 
605 /* Returns true if we were able to get the version / offset information
606  * out of libBacktraceRecording.  false means we were unable to retrieve
607  * this; the queue_info_version field will be 0.
608  */
609 
610 bool
611 SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized ()
612 {
613     if (m_lib_backtrace_recording_info.queue_info_version != 0)
614         return true;
615 
616     addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
617     addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
618     addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
619     addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
620     Target &target = m_process->GetTarget();
621 
622 
623     static ConstString introspection_dispatch_queue_info_version ("__introspection_dispatch_queue_info_version");
624     SymbolContextList sc_list;
625     if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_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         queue_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
632     }
633     sc_list.Clear();
634 
635     static ConstString introspection_dispatch_queue_info_data_offset ("__introspection_dispatch_queue_info_data_offset");
636     if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_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         queue_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
643     }
644     sc_list.Clear();
645 
646     static ConstString introspection_dispatch_item_info_version ("__introspection_dispatch_item_info_version");
647     if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > 0)
648     {
649         SymbolContext sc;
650         sc_list.GetContextAtIndex (0, sc);
651         AddressRange addr_range;
652         sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
653         item_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
654     }
655     sc_list.Clear();
656 
657     static ConstString introspection_dispatch_item_info_data_offset ("__introspection_dispatch_item_info_data_offset");
658     if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list) > 0)
659     {
660         SymbolContext sc;
661         sc_list.GetContextAtIndex (0, sc);
662         AddressRange addr_range;
663         sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
664         item_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
665     }
666 
667     if (queue_info_version_address != LLDB_INVALID_ADDRESS
668         && queue_info_data_offset_address != LLDB_INVALID_ADDRESS
669         && item_info_version_address != LLDB_INVALID_ADDRESS
670         && item_info_data_offset_address != LLDB_INVALID_ADDRESS)
671     {
672         Error error;
673         m_lib_backtrace_recording_info.queue_info_version = m_process->ReadUnsignedIntegerFromMemory (queue_info_version_address, 2, 0, error);
674         if (error.Success())
675         {
676             m_lib_backtrace_recording_info.queue_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (queue_info_data_offset_address, 2, 0, error);
677             if (error.Success())
678             {
679                 m_lib_backtrace_recording_info.item_info_version = m_process->ReadUnsignedIntegerFromMemory (item_info_version_address, 2, 0, error);
680                 if (error.Success())
681                 {
682                     m_lib_backtrace_recording_info.item_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (item_info_data_offset_address, 2, 0, error);
683                     if (!error.Success())
684                     {
685                         m_lib_backtrace_recording_info.queue_info_version = 0;
686                     }
687                 }
688                 else
689                 {
690                     m_lib_backtrace_recording_info.queue_info_version = 0;
691                 }
692             }
693             else
694             {
695                 m_lib_backtrace_recording_info.queue_info_version = 0;
696             }
697         }
698     }
699 
700     return m_lib_backtrace_recording_info.queue_info_version != 0;
701 }
702 
703 const std::vector<ConstString> &
704 SystemRuntimeMacOSX::GetExtendedBacktraceTypes ()
705 {
706     if (m_types.size () == 0)
707     {
708         m_types.push_back(ConstString("libdispatch"));
709         // We could have pthread as another type in the future if we have a way of
710         // gathering that information & it's useful to distinguish between them.
711     }
712     return m_types;
713 }
714 
715 void
716 SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
717 {
718     if (BacktraceRecordingHeadersInitialized())
719     {
720         AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
721         ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
722         if (cur_thread_sp)
723         {
724             Error error;
725             queue_info_pointer = m_get_queues_handler.GetCurrentQueues (*cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
726             m_page_to_free = LLDB_INVALID_ADDRESS;
727             m_page_to_free_size = 0;
728             if (error.Success())
729             {
730 
731                 if (queue_info_pointer.count > 0
732                     && queue_info_pointer.queues_buffer_size > 0
733                     && queue_info_pointer.queues_buffer_ptr != 0
734                     && queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS)
735                 {
736                     PopulateQueuesUsingLibBTR (queue_info_pointer.queues_buffer_ptr, queue_info_pointer.queues_buffer_size, queue_info_pointer.count, queue_list);
737                 }
738             }
739         }
740     }
741 
742     // We either didn't have libBacktraceRecording (and need to create the queues list based on threads)
743     // or we did get the queues list from libBacktraceRecording but some special queues may not be
744     // included in its information.  This is needed because libBacktraceRecording
745     // will only list queues with pending or running items by default - but the magic com.apple.main-thread
746     // queue on thread 1 is always around.
747 
748     for (ThreadSP thread_sp : m_process->Threads())
749     {
750         if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
751         {
752             if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
753             {
754                 QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
755                 queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
756                 queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
757                 queue_list.AddQueue (queue_sp);
758             }
759         }
760     }
761 }
762 
763 // Returns either an array of introspection_dispatch_item_info_ref's for the pending items on
764 // a queue or an array introspection_dispatch_item_info_ref's and code addresses for the
765 // pending items on a queue.  The information about each of these pending items then needs to
766 // be fetched individually by passing the ref to libBacktraceRecording.
767 
768 SystemRuntimeMacOSX::PendingItemsForQueue
769 SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
770 {
771     PendingItemsForQueue pending_item_refs;
772     AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
773     ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
774     if (cur_thread_sp)
775     {
776         Error error;
777         pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error);
778         m_page_to_free = LLDB_INVALID_ADDRESS;
779         m_page_to_free_size = 0;
780         if (error.Success())
781         {
782             if (pending_items_pointer.count > 0
783                 && pending_items_pointer.items_buffer_size > 0
784                 && pending_items_pointer.items_buffer_ptr != 0
785                 && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS)
786             {
787                 DataBufferHeap data (pending_items_pointer.items_buffer_size, 0);
788                 if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error))
789                 {
790                     DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
791 
792                     // We either have an array of
793                     //    void* item_ref
794                     // (old style) or we have a structure returned which looks like
795                     //
796                     // struct introspection_dispatch_pending_item_info_s {
797                     //   void *item_ref;
798                     //   void *function_or_block;
799                     // };
800                     //
801                     // struct introspection_dispatch_pending_items_array_s {
802                     //   uint32_t version;
803                     //   uint32_t size_of_item_info;
804                     //   introspection_dispatch_pending_item_info_s items[];
805                     //   }
806 
807                     offset_t offset = 0;
808                     int i = 0;
809                     uint32_t version = extractor.GetU32(&offset);
810                     if (version == 1)
811                     {
812                         pending_item_refs.new_style = true;
813                         uint32_t item_size = extractor.GetU32(&offset);
814                         uint32_t start_of_array_offset = offset;
815                         while (offset < pending_items_pointer.items_buffer_size &&
816                                static_cast<size_t>(i) < pending_items_pointer.count)
817                         {
818                             offset = start_of_array_offset + (i * item_size);
819                             ItemRefAndCodeAddress item;
820                             item.item_ref = extractor.GetPointer (&offset);
821                             item.code_address = extractor.GetPointer (&offset);
822                             pending_item_refs.item_refs_and_code_addresses.push_back (item);
823                             i++;
824                         }
825                     }
826                     else
827                     {
828                         offset = 0;
829                         pending_item_refs.new_style = false;
830                         while (offset < pending_items_pointer.items_buffer_size &&
831                                static_cast<size_t>(i) < pending_items_pointer.count)
832                         {
833                             ItemRefAndCodeAddress item;
834                             item.item_ref = extractor.GetPointer (&offset);
835                             item.code_address = LLDB_INVALID_ADDRESS;
836                             pending_item_refs.item_refs_and_code_addresses.push_back (item);
837                             i++;
838                         }
839                     }
840                 }
841                 m_page_to_free = pending_items_pointer.items_buffer_ptr;
842                 m_page_to_free_size = pending_items_pointer.items_buffer_size;
843             }
844         }
845     }
846     return pending_item_refs;
847 }
848 
849 
850 
851 void
852 SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
853 {
854     if (BacktraceRecordingHeadersInitialized())
855     {
856         PendingItemsForQueue pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
857         for (ItemRefAndCodeAddress pending_item : pending_item_refs.item_refs_and_code_addresses)
858         {
859             Address addr;
860             m_process->GetTarget().ResolveLoadAddress (pending_item.code_address, addr);
861             QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this(), m_process->shared_from_this(), pending_item.item_ref, addr));
862             queue->PushPendingQueueItem (queue_item_sp);
863         }
864     }
865 }
866 
867 void
868 SystemRuntimeMacOSX::CompleteQueueItem (QueueItem *queue_item, addr_t item_ref)
869 {
870     AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
871 
872     ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
873     Error error;
874     ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
875     m_page_to_free = LLDB_INVALID_ADDRESS;
876     m_page_to_free_size = 0;
877     if (ret.item_buffer_ptr != 0 &&  ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
878     {
879         DataBufferHeap data (ret.item_buffer_size, 0);
880         if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
881         {
882             DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
883             ItemInfo item = ExtractItemInfoFromBuffer (extractor);
884             queue_item->SetItemThatEnqueuedThis (item.item_that_enqueued_this);
885             queue_item->SetEnqueueingThreadID (item.enqueuing_thread_id);
886             queue_item->SetEnqueueingQueueID (item.enqueuing_queue_serialnum);
887             queue_item->SetStopID (item.stop_id);
888             queue_item->SetEnqueueingBacktrace (item.enqueuing_callstack);
889             queue_item->SetThreadLabel (item.enqueuing_thread_label);
890             queue_item->SetQueueLabel (item.enqueuing_queue_label);
891             queue_item->SetTargetQueueLabel (item.target_queue_label);
892         }
893         m_page_to_free = ret.item_buffer_ptr;
894         m_page_to_free_size = ret.item_buffer_size;
895     }
896 }
897 
898 void
899 SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
900                                                 uint64_t count, lldb_private::QueueList &queue_list)
901 {
902     Error error;
903     DataBufferHeap data (queues_buffer_size, 0);
904     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
905     if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
906     {
907         // We've read the information out of inferior memory; free it on the next call we make
908         m_page_to_free = queues_buffer;
909         m_page_to_free_size = queues_buffer_size;
910 
911         DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
912         offset_t offset = 0;
913         uint64_t queues_read = 0;
914 
915         // The information about the queues is stored in this format (v1):
916         // typedef struct introspection_dispatch_queue_info_s {
917         //     uint32_t offset_to_next;
918         //     dispatch_queue_t queue;
919         //     uint64_t serialnum;     // queue's serialnum in the process, as provided by libdispatch
920         //     uint32_t running_work_items_count;
921         //     uint32_t pending_work_items_count;
922         //
923         //     char data[];     // Starting here, we have variable-length data:
924         //     // char queue_label[];
925         // } introspection_dispatch_queue_info_s;
926 
927         while (queues_read < count && offset < queues_buffer_size)
928         {
929             offset_t    start_of_this_item = offset;
930 
931             uint32_t    offset_to_next = extractor.GetU32 (&offset);
932 
933             offset += 4; // Skip over the 4 bytes of reserved space
934             addr_t      queue = extractor.GetPointer (&offset);
935             uint64_t    serialnum = extractor.GetU64 (&offset);
936             uint32_t    running_work_items_count = extractor.GetU32 (&offset);
937             uint32_t    pending_work_items_count = extractor.GetU32 (&offset);
938 
939             // Read the first field of the variable length data
940             offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
941             const char *queue_label = extractor.GetCStr (&offset);
942             if (queue_label == NULL)
943                 queue_label = "";
944 
945             offset_t    start_of_next_item = start_of_this_item + offset_to_next;
946             offset = start_of_next_item;
947 
948             if (log)
949                 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);
950 
951             QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
952             queue_sp->SetNumRunningWorkItems (running_work_items_count);
953             queue_sp->SetNumPendingWorkItems (pending_work_items_count);
954             queue_sp->SetLibdispatchQueueAddress (queue);
955             queue_sp->SetKind (GetQueueKind (queue));
956             queue_list.AddQueue (queue_sp);
957             queues_read++;
958         }
959     }
960 }
961 
962 SystemRuntimeMacOSX::ItemInfo
963 SystemRuntimeMacOSX::ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor)
964 {
965     ItemInfo item;
966 
967     offset_t offset = 0;
968 
969     item.item_that_enqueued_this = extractor.GetPointer (&offset);
970     item.function_or_block = extractor.GetPointer (&offset);
971     item.enqueuing_thread_id = extractor.GetU64 (&offset);
972     item.enqueuing_queue_serialnum = extractor.GetU64 (&offset);
973     item.target_queue_serialnum = extractor.GetU64 (&offset);
974     item.enqueuing_callstack_frame_count = extractor.GetU32 (&offset);
975     item.stop_id = extractor.GetU32 (&offset);
976 
977     offset = m_lib_backtrace_recording_info.item_info_data_offset;
978 
979     for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++)
980     {
981         item.enqueuing_callstack.push_back (extractor.GetPointer (&offset));
982     }
983     item.enqueuing_thread_label = extractor.GetCStr (&offset);
984     item.enqueuing_queue_label = extractor.GetCStr (&offset);
985     item.target_queue_label = extractor.GetCStr (&offset);
986 
987     return item;
988 }
989 
990 void
991 SystemRuntimeMacOSX::Initialize()
992 {
993     PluginManager::RegisterPlugin (GetPluginNameStatic(),
994                                    GetPluginDescriptionStatic(),
995                                    CreateInstance);
996 }
997 
998 void
999 SystemRuntimeMacOSX::Terminate()
1000 {
1001     PluginManager::UnregisterPlugin (CreateInstance);
1002 }
1003 
1004 
1005 lldb_private::ConstString
1006 SystemRuntimeMacOSX::GetPluginNameStatic()
1007 {
1008     static ConstString g_name("systemruntime-macosx");
1009     return g_name;
1010 }
1011 
1012 const char *
1013 SystemRuntimeMacOSX::GetPluginDescriptionStatic()
1014 {
1015     return "System runtime plugin for Mac OS X native libraries.";
1016 }
1017 
1018 
1019 //------------------------------------------------------------------
1020 // PluginInterface protocol
1021 //------------------------------------------------------------------
1022 lldb_private::ConstString
1023 SystemRuntimeMacOSX::GetPluginName()
1024 {
1025     return GetPluginNameStatic();
1026 }
1027 
1028 uint32_t
1029 SystemRuntimeMacOSX::GetPluginVersion()
1030 {
1031     return 1;
1032 }
1033