blob: fd7050775667c8b6e4d5e22c468800415a31f0bc [file] [log] [blame]
Jason Molendaa7b5afa2013-11-15 00:17:32 +00001//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11#include "lldb/Breakpoint/StoppointCallbackContext.h"
12#include "lldb/Core/Log.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/ModuleSpec.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/DataBufferHeap.h"
18#include "lldb/Core/Section.h"
19#include "lldb/Expression/ClangFunction.h"
20#include "lldb/Expression/ClangUtilityFunction.h"
21#include "lldb/Host/FileSpec.h"
22#include "lldb/Symbol/ObjectFile.h"
23#include "lldb/Symbol/SymbolContext.h"
24#include "Plugins/Process/Utility/HistoryThread.h"
Jason Molenda5e8dce42013-12-13 00:29:16 +000025#include "lldb/Target/Queue.h"
26#include "lldb/Target/QueueList.h"
Jason Molendaa7b5afa2013-11-15 00:17:32 +000027#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
Jason Molenda2fd83352014-02-05 05:44:54 +000029#include "lldb/Target/Process.h"
30
Jason Molendaa7b5afa2013-11-15 00:17:32 +000031
Jason Molendaa7b5afa2013-11-15 00:17:32 +000032#include "SystemRuntimeMacOSX.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37//----------------------------------------------------------------------
38// Create an instance of this class. This function is filled into
39// the plugin info class that gets handed out by the plugin factory and
40// allows the lldb to instantiate an instance of this class.
41//----------------------------------------------------------------------
42SystemRuntime *
43SystemRuntimeMacOSX::CreateInstance (Process* process)
44{
45 bool create = false;
46 if (!create)
47 {
48 create = true;
49 Module* exe_module = process->GetTarget().GetExecutableModulePointer();
50 if (exe_module)
51 {
52 ObjectFile *object_file = exe_module->GetObjectFile();
53 if (object_file)
54 {
55 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
56 }
57 }
58
59 if (create)
60 {
61 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
62 switch (triple_ref.getOS())
63 {
64 case llvm::Triple::Darwin:
65 case llvm::Triple::MacOSX:
66 case llvm::Triple::IOS:
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//----------------------------------------------------------------------
84SystemRuntimeMacOSX::SystemRuntimeMacOSX (Process* process) :
85 SystemRuntime(process),
86 m_break_id(LLDB_INVALID_BREAK_ID),
Jason Molenda2fd83352014-02-05 05:44:54 +000087 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()
Jason Molendaa7b5afa2013-11-15 00:17:32 +000097{
Jason Molendaa7b5afa2013-11-15 00:17:32 +000098}
99
100//----------------------------------------------------------------------
101// Destructor
102//----------------------------------------------------------------------
103SystemRuntimeMacOSX::~SystemRuntimeMacOSX()
104{
105 Clear (true);
106}
107
Jason Molenda2fd83352014-02-05 05:44:54 +0000108void
109SystemRuntimeMacOSX::Detach ()
110{
111 m_get_queues_handler.Detach();
112 m_get_pending_items_handler.Detach();
113 m_get_item_info_handler.Detach();
114 m_get_thread_item_info_handler.Detach();
115}
116
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000117//----------------------------------------------------------------------
118// Clear out the state of this class.
119//----------------------------------------------------------------------
120void
121SystemRuntimeMacOSX::Clear (bool clear_process)
122{
123 Mutex::Locker locker(m_mutex);
124
125 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
126 m_process->ClearBreakpointSiteByID(m_break_id);
127
128 if (clear_process)
129 m_process = NULL;
130 m_break_id = LLDB_INVALID_BREAK_ID;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000131}
132
133
Jason Molenda2fd83352014-02-05 05:44:54 +0000134std::string
135SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress (addr_t dispatch_qaddr)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000136{
Jason Molenda2fd83352014-02-05 05:44:54 +0000137 std::string dispatch_queue_name;
138 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
139 return "";
140
141 ReadLibdispatchOffsets ();
142 if (m_libdispatch_offsets.IsValid ())
143 {
144 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a thread -
145 // deref it to get the address of the dispatch_queue_t structure for this thread's
146 // queue.
147 Error error;
148 addr_t dispatch_queue_addr = m_process->ReadPointerFromMemory (dispatch_qaddr, error);
149 if (error.Success())
150 {
151 if (m_libdispatch_offsets.dqo_version >= 4)
152 {
153 // libdispatch versions 4+, pointer to dispatch name is in the
154 // queue structure.
155 addr_t pointer_to_label_address = dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
156 addr_t label_addr = m_process->ReadPointerFromMemory (pointer_to_label_address, error);
157 if (error.Success())
158 {
159 m_process->ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
160 }
161 }
162 else
163 {
164 // libdispatch versions 1-3, dispatch name is a fixed width char array
165 // in the queue structure.
166 addr_t label_addr = dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
167 dispatch_queue_name.resize (m_libdispatch_offsets.dqo_label_size, '\0');
168 size_t bytes_read = m_process->ReadMemory (label_addr, &dispatch_queue_name[0], m_libdispatch_offsets.dqo_label_size, error);
169 if (bytes_read < m_libdispatch_offsets.dqo_label_size)
170 dispatch_queue_name.erase (bytes_read);
171 }
172 }
173 }
174 return dispatch_queue_name;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000175}
176
Jason Molenda2fd83352014-02-05 05:44:54 +0000177lldb::queue_id_t
178SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress (lldb::addr_t dispatch_qaddr)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000179{
Jason Molenda2fd83352014-02-05 05:44:54 +0000180 queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
181
182 if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0)
183 return queue_id;
184
185 ReadLibdispatchOffsets ();
186 if (m_libdispatch_offsets.IsValid ())
187 {
188 // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a thread -
189 // deref it to get the address of the dispatch_queue_t structure for this thread's
190 // queue.
191 Error error;
192 uint64_t dispatch_queue_addr = m_process->ReadPointerFromMemory (dispatch_qaddr, error);
193 if (error.Success())
194 {
195 addr_t serialnum_address = dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum;
196 queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory (serialnum_address, m_libdispatch_offsets.dqo_serialnum_size, LLDB_INVALID_QUEUE_ID, error);
197 if (error.Success())
198 {
199 queue_id = serialnum;
200 }
201 }
202 }
203
204 return queue_id;
205}
206
207
208void
209SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress ()
210{
211 if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS)
212 return;
213
214 static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
215 const Symbol *dispatch_queue_offsets_symbol = NULL;
216
217 // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 ("Snow Leopard")
218 ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
219 ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
220 if (module_sp)
221 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
222
223 // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and later
224 if (dispatch_queue_offsets_symbol == NULL)
225 {
226 ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
227 module_sp = m_process->GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
228 if (module_sp)
229 dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
230 }
231 if (dispatch_queue_offsets_symbol)
232 m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_process->GetTarget());
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000233}
234
235void
Jason Molenda2fd83352014-02-05 05:44:54 +0000236SystemRuntimeMacOSX::ReadLibdispatchOffsets ()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000237{
Jason Molenda2fd83352014-02-05 05:44:54 +0000238 if (m_libdispatch_offsets.IsValid())
239 return;
240
241 ReadLibdispatchOffsetsAddress ();
242
243 uint8_t memory_buffer[sizeof (struct LibdispatchOffsets)];
244 DataExtractor data (memory_buffer,
245 sizeof(memory_buffer),
246 m_process->GetByteOrder(),
247 m_process->GetAddressByteSize());
248
249 Error error;
250 if (m_process->ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(memory_buffer), error) == sizeof(memory_buffer))
251 {
252 lldb::offset_t data_offset = 0;
253
254 // The struct LibdispatchOffsets is a series of uint16_t's - extract them all
255 // in one big go.
256 data.GetU16 (&data_offset, &m_libdispatch_offsets.dqo_version, sizeof (struct LibdispatchOffsets) / sizeof (uint16_t));
257 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000258}
259
Jason Molenda2fd83352014-02-05 05:44:54 +0000260
261ThreadSP
262SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type)
263{
264 ThreadSP originating_thread_sp;
265 if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch"))
266 {
267 Error error;
268
269 // real_thread is either an actual, live thread (in which case we need to call into
270 // libBacktraceRecording to find its originator) or it is an extended backtrace itself,
271 // in which case we get the token from it and call into libBacktraceRecording to find
272 // the originator of that token.
273
274 if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS)
275 {
276 originating_thread_sp = GetExtendedBacktraceFromItemRef (real_thread->GetExtendedBacktraceToken());
277 }
278 else
279 {
280 AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret = m_get_thread_item_info_handler.GetThreadItemInfo (*real_thread.get(), m_page_to_free, m_page_to_free_size, error);
281 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
282 {
283 DataBufferHeap data (ret.item_buffer_size, 0);
284 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
285 {
286 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
287 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
288 bool stop_id_is_valid = true;
289 if (item.stop_id == 0)
290 stop_id_is_valid = false;
291 originating_thread_sp.reset (new HistoryThread (*m_process,
292 item.enqueuing_thread_id,
293 item.enqueuing_callstack,
294 item.stop_id,
295 stop_id_is_valid));
296 originating_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
297 originating_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
298 originating_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
299// originating_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
300 }
301 }
302 }
303 }
304 return originating_thread_sp;
305}
306
307ThreadSP
308SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref)
309{
310 ThreadSP return_thread_sp;
311
312 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
313 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
314 Error error;
315 ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error);
316 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
317 {
318 DataBufferHeap data (ret.item_buffer_size, 0);
319 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
320 {
321 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
322 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
323 bool stop_id_is_valid = true;
324 if (item.stop_id == 0)
325 stop_id_is_valid = false;
326 return_thread_sp.reset (new HistoryThread (*m_process,
327 item.enqueuing_thread_id,
328 item.enqueuing_callstack,
329 item.stop_id,
330 stop_id_is_valid));
331 return_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this);
332 return_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str());
333 return_thread_sp->SetQueueID (item.enqueuing_queue_serialnum);
334// return_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str());
335
336 }
337 }
338 return return_thread_sp;
339}
340
341ThreadSP
342SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem (QueueItemSP queue_item_sp, ConstString type)
343{
344 ThreadSP extended_thread_sp;
345 if (type != ConstString("libdispatch"))
346 return extended_thread_sp;
347
348 bool stop_id_is_valid = true;
349 if (queue_item_sp->GetStopID() == 0)
350 stop_id_is_valid = false;
351
352 extended_thread_sp.reset (new HistoryThread (*m_process,
353 queue_item_sp->GetEnqueueingThreadID(),
354 queue_item_sp->GetEnqueueingBacktrace(),
355 queue_item_sp->GetStopID(),
356 stop_id_is_valid));
357 extended_thread_sp->SetExtendedBacktraceToken (queue_item_sp->GetItemThatEnqueuedThis());
358 extended_thread_sp->SetQueueName (queue_item_sp->GetQueueLabel().c_str());
359 extended_thread_sp->SetQueueID (queue_item_sp->GetEnqueueingQueueID());
360// extended_thread_sp->SetThreadName (queue_item_sp->GetThreadLabel().c_str());
361
362 return extended_thread_sp;
363}
364
365/* Returns true if we were able to get the version / offset information
366 * out of libBacktraceRecording. false means we were unable to retrieve
367 * this; the queue_info_version field will be 0.
368 */
369
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000370bool
Jason Molenda2fd83352014-02-05 05:44:54 +0000371SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized ()
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000372{
Jason Molenda2fd83352014-02-05 05:44:54 +0000373 if (m_lib_backtrace_recording_info.queue_info_version != 0)
374 return true;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000375
Jason Molenda2fd83352014-02-05 05:44:54 +0000376 addr_t queue_info_version_address = LLDB_INVALID_ADDRESS;
377 addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS;
378 addr_t item_info_version_address = LLDB_INVALID_ADDRESS;
379 addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS;
380 Target &target = m_process->GetTarget();
381
382
383 static ConstString introspection_dispatch_queue_info_version ("__introspection_dispatch_queue_info_version");
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000384 SymbolContextList sc_list;
Jason Molenda2fd83352014-02-05 05:44:54 +0000385 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > 0)
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000386 {
387 SymbolContext sc;
388 sc_list.GetContextAtIndex (0, sc);
389 AddressRange addr_range;
390 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
Jason Molenda2fd83352014-02-05 05:44:54 +0000391 queue_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
392 }
393 sc_list.Clear();
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000394
Jason Molenda2fd83352014-02-05 05:44:54 +0000395 static ConstString introspection_dispatch_queue_info_data_offset ("__introspection_dispatch_queue_info_data_offset");
396 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_queue_info_data_offset, eSymbolTypeData, sc_list) > 0)
397 {
398 SymbolContext sc;
399 sc_list.GetContextAtIndex (0, sc);
400 AddressRange addr_range;
401 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
402 queue_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
403 }
404 sc_list.Clear();
405
406 static ConstString introspection_dispatch_item_info_version ("__introspection_dispatch_item_info_version");
407 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > 0)
408 {
409 SymbolContext sc;
410 sc_list.GetContextAtIndex (0, sc);
411 AddressRange addr_range;
412 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
413 item_info_version_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
414 }
415 sc_list.Clear();
416
417 static ConstString introspection_dispatch_item_info_data_offset ("__introspection_dispatch_item_info_data_offset");
418 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (introspection_dispatch_item_info_data_offset, eSymbolTypeData, sc_list) > 0)
419 {
420 SymbolContext sc;
421 sc_list.GetContextAtIndex (0, sc);
422 AddressRange addr_range;
423 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
424 item_info_data_offset_address = addr_range.GetBaseAddress().GetLoadAddress(&target);
425 }
426
427 if (queue_info_version_address != LLDB_INVALID_ADDRESS
428 && queue_info_data_offset_address != LLDB_INVALID_ADDRESS
429 && item_info_version_address != LLDB_INVALID_ADDRESS
430 && item_info_data_offset_address != LLDB_INVALID_ADDRESS)
431 {
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000432 Error error;
Jason Molenda2fd83352014-02-05 05:44:54 +0000433 m_lib_backtrace_recording_info.queue_info_version = m_process->ReadUnsignedIntegerFromMemory (queue_info_version_address, 2, 0, error);
434 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000435 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000436 m_lib_backtrace_recording_info.queue_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (queue_info_data_offset_address, 2, 0, error);
437 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000438 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000439 m_lib_backtrace_recording_info.item_info_version = m_process->ReadUnsignedIntegerFromMemory (item_info_version_address, 2, 0, error);
440 if (error.Success())
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000441 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000442 m_lib_backtrace_recording_info.item_info_data_offset = m_process->ReadUnsignedIntegerFromMemory (item_info_data_offset_address, 2, 0, error);
443 if (!error.Success())
Jason Molendaa6e91302013-11-19 05:44:41 +0000444 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000445 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa6e91302013-11-19 05:44:41 +0000446 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000447 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000448 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000449 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000450 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000451 }
452 }
Jason Molenda2fd83352014-02-05 05:44:54 +0000453 else
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000454 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000455 m_lib_backtrace_recording_info.queue_info_version = 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000456 }
457 }
458 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000459
Jason Molenda2fd83352014-02-05 05:44:54 +0000460 return m_lib_backtrace_recording_info.queue_info_version != 0;
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000461}
462
463const std::vector<ConstString> &
464SystemRuntimeMacOSX::GetExtendedBacktraceTypes ()
465{
466 if (m_types.size () == 0)
467 {
468 m_types.push_back(ConstString("libdispatch"));
Jason Molenda2fd83352014-02-05 05:44:54 +0000469 // We could have pthread as another type in the future if we have a way of
470 // gathering that information & it's useful to distinguish between them.
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000471 }
472 return m_types;
473}
474
475void
Jason Molenda5e8dce42013-12-13 00:29:16 +0000476SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
477{
Jason Molenda2fd83352014-02-05 05:44:54 +0000478 if (!BacktraceRecordingHeadersInitialized())
Jason Molenda5e8dce42013-12-13 00:29:16 +0000479 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000480 // We don't have libBacktraceRecording -- build the list of queues by looking at
481 // all extant threads, and the queues that they currently belong to.
482
483 for (ThreadSP thread_sp : m_process->Threads())
Jason Molenda5e8dce42013-12-13 00:29:16 +0000484 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000485 if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
Jason Molenda5e8dce42013-12-13 00:29:16 +0000486 {
Jason Molenda2fd83352014-02-05 05:44:54 +0000487 if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
488 {
489 QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
490 queue_list.AddQueue (queue_sp);
491 }
492 }
493 }
494 }
495 else
496 {
497 AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer;
498 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
499 if (cur_thread_sp)
500 {
501 Error error;
502 queue_info_pointer = m_get_queues_handler.GetCurrentQueues (*cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error);
503 if (error.Success())
504 {
505 m_page_to_free = LLDB_INVALID_ADDRESS;
506 m_page_to_free_size = 0;
507
508 if (queue_info_pointer.count > 0
509 && queue_info_pointer.queues_buffer_size > 0
510 && queue_info_pointer.queues_buffer_ptr != 0
511 && queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS)
512 {
513 PopulateQueuesUsingLibBTR (queue_info_pointer.queues_buffer_ptr, queue_info_pointer.queues_buffer_size, queue_info_pointer.count, queue_list);
514 }
Jason Molenda5e8dce42013-12-13 00:29:16 +0000515 }
516 }
517 }
518}
519
Jason Molenda2fd83352014-02-05 05:44:54 +0000520void
521SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
522{
523 if (BacktraceRecordingHeadersInitialized())
524 {
525 std::vector<addr_t> pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
526 for (addr_t pending_item : pending_item_refs)
527 {
528 AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
529 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
530 Error error;
531 ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), pending_item, m_page_to_free, m_page_to_free_size, error);
532 if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0)
533 {
534 DataBufferHeap data (ret.item_buffer_size, 0);
535 if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success())
536 {
537 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
538 ItemInfo item = ExtractItemInfoFromBuffer (extractor);
539 QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this()));
540 queue_item_sp->SetItemThatEnqueuedThis (item.item_that_enqueued_this);
541
542 Address addr;
543 if (!m_process->GetTarget().ResolveLoadAddress (item.function_or_block, addr, item.stop_id))
544 {
545 m_process->GetTarget().ResolveLoadAddress (item.function_or_block, addr);
546 }
547 queue_item_sp->SetAddress (addr);
548 queue_item_sp->SetEnqueueingThreadID (item.enqueuing_thread_id);
549 queue_item_sp->SetTargetQueueID (item.enqueuing_thread_id);
550 queue_item_sp->SetStopID (item.stop_id);
551 queue_item_sp->SetEnqueueingBacktrace (item.enqueuing_callstack);
552 queue_item_sp->SetThreadLabel (item.enqueuing_thread_label);
553 queue_item_sp->SetQueueLabel (item.enqueuing_queue_label);
554 queue_item_sp->SetTargetQueueLabel (item.target_queue_label);
555
556 queue->PushPendingQueueItem (queue_item_sp);
557 }
558 }
559 }
560 }
561}
562
563// Returns an array of introspection_dispatch_item_info_ref's for the pending items on
564// a queue. The information about each of these pending items then needs to be fetched
565// individually by passing the ref to libBacktraceRecording.
566
567std::vector<lldb::addr_t>
568SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
569{
570 std::vector<addr_t> pending_item_refs;
571 AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
572 ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
573 if (cur_thread_sp)
574 {
575 Error error;
576 pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error);
577 if (error.Success())
578 {
579 m_page_to_free = LLDB_INVALID_ADDRESS;
580 m_page_to_free_size = 0;
581 if (pending_items_pointer.count > 0
582 && pending_items_pointer.items_buffer_size > 0
583 && pending_items_pointer.items_buffer_ptr != 0
584 && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS)
585 {
586 DataBufferHeap data (pending_items_pointer.items_buffer_size, 0);
587 if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error))
588 {
589 offset_t offset = 0;
590 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
591 int i = 0;
592 while (offset < pending_items_pointer.items_buffer_size && i < pending_items_pointer.count)
593 {
594 pending_item_refs.push_back (extractor.GetPointer (&offset));
595 i++;
596 }
597 }
598 m_page_to_free = pending_items_pointer.items_buffer_ptr;
599 m_page_to_free_size = pending_items_pointer.items_buffer_size;
600 }
601 }
602 }
603 return pending_item_refs;
604}
605
606
607void
608SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
609 uint64_t count, lldb_private::QueueList &queue_list)
610{
611 Error error;
612 DataBufferHeap data (queues_buffer_size, 0);
613 if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success())
614 {
615 // We've read the information out of inferior memory; free it on the next call we make
616 m_page_to_free = queues_buffer;
617 m_page_to_free_size = queues_buffer_size;
618
619 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
620 offset_t offset = 0;
621 uint64_t queues_read = 0;
622
623 // The information about the queues is stored in this format (v1):
624 // typedef struct introspection_dispatch_queue_info_s {
625 // uint32_t offset_to_next;
626 // dispatch_queue_t queue;
627 // uint64_t serialnum; // queue's serialnum in the process, as provided by libdispatch
628 // uint32_t running_work_items_count;
629 // uint32_t pending_work_items_count;
630 //
631 // char data[]; // Starting here, we have variable-length data:
632 // // char queue_label[];
633 // } introspection_dispatch_queue_info_s;
634
635 while (queues_read < count && offset < queues_buffer_size)
636 {
637 offset_t start_of_this_item = offset;
638
639 uint32_t offset_to_next = extractor.GetU32 (&offset);
640 /* on 64-bit architectures, the pointer will be 8-byte aligned so there's 4 bytes of
641 * padding between these fields.
642 */
643 if (m_process->GetAddressByteSize() == 8)
644 offset += 4;
645 addr_t queue = extractor.GetPointer (&offset);
646 uint64_t serialnum = extractor.GetU64 (&offset);
647 uint32_t running_work_items_count = extractor.GetU32 (&offset);
648 uint32_t pending_work_items_count = extractor.GetU32 (&offset);
649
650 // Read the first field of the variable length data
651 offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset;
652 const char *queue_label = extractor.GetCStr (&offset);
653 if (queue_label == NULL)
654 queue_label = "";
655
656 offset_t start_of_next_item = start_of_this_item + offset_to_next;
657 offset = start_of_next_item;
658
659 QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label));
660 queue_sp->SetNumRunningWorkItems (running_work_items_count);
661 queue_sp->SetNumPendingWorkItems (pending_work_items_count);
662 queue_sp->SetLibdispatchQueueAddress (queue);
663 queue_list.AddQueue (queue_sp);
664 queues_read++;
665 }
666 }
667}
668
669SystemRuntimeMacOSX::ItemInfo
670SystemRuntimeMacOSX::ExtractItemInfoFromBuffer (lldb_private::DataExtractor &extractor)
671{
672 ItemInfo item;
673
674 offset_t offset = 0;
675
676 item.item_that_enqueued_this = extractor.GetPointer (&offset);
677 item.function_or_block = extractor.GetPointer (&offset);
678 item.enqueuing_thread_id = extractor.GetU64 (&offset);
679 item.enqueuing_queue_serialnum = extractor.GetU64 (&offset);
680 item.target_queue_serialnum = extractor.GetU64 (&offset);
681 item.enqueuing_callstack_frame_count = extractor.GetU32 (&offset);
682 item.stop_id = extractor.GetU32 (&offset);
683
684 offset = m_lib_backtrace_recording_info.item_info_data_offset;
685
686 for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++)
687 {
688 item.enqueuing_callstack.push_back (extractor.GetPointer (&offset));
689 }
690 item.enqueuing_thread_label = extractor.GetCStr (&offset);
691 item.enqueuing_queue_label = extractor.GetCStr (&offset);
692 item.target_queue_label = extractor.GetCStr (&offset);
693
694 return item;
695}
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000696
697void
698SystemRuntimeMacOSX::Initialize()
699{
700 PluginManager::RegisterPlugin (GetPluginNameStatic(),
701 GetPluginDescriptionStatic(),
702 CreateInstance);
703}
704
705void
706SystemRuntimeMacOSX::Terminate()
707{
708 PluginManager::UnregisterPlugin (CreateInstance);
709}
710
711
712lldb_private::ConstString
713SystemRuntimeMacOSX::GetPluginNameStatic()
714{
715 static ConstString g_name("systemruntime-macosx");
716 return g_name;
717}
718
719const char *
720SystemRuntimeMacOSX::GetPluginDescriptionStatic()
721{
722 return "System runtime plugin for Mac OS X native libraries.";
723}
724
725
726//------------------------------------------------------------------
727// PluginInterface protocol
728//------------------------------------------------------------------
729lldb_private::ConstString
730SystemRuntimeMacOSX::GetPluginName()
731{
732 return GetPluginNameStatic();
733}
734
735uint32_t
736SystemRuntimeMacOSX::GetPluginVersion()
737{
738 return 1;
739}