blob: 388264a2d957c5e08f7ccd807c1b8864816d0ad9 [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"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27
28
29#include "SystemRuntimeMacOSX.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// Create an instance of this class. This function is filled into
36// the plugin info class that gets handed out by the plugin factory and
37// allows the lldb to instantiate an instance of this class.
38//----------------------------------------------------------------------
39SystemRuntime *
40SystemRuntimeMacOSX::CreateInstance (Process* process)
41{
42 bool create = false;
43 if (!create)
44 {
45 create = true;
46 Module* exe_module = process->GetTarget().GetExecutableModulePointer();
47 if (exe_module)
48 {
49 ObjectFile *object_file = exe_module->GetObjectFile();
50 if (object_file)
51 {
52 create = (object_file->GetStrata() == ObjectFile::eStrataUser);
53 }
54 }
55
56 if (create)
57 {
58 const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
59 switch (triple_ref.getOS())
60 {
61 case llvm::Triple::Darwin:
62 case llvm::Triple::MacOSX:
63 case llvm::Triple::IOS:
64 create = triple_ref.getVendor() == llvm::Triple::Apple;
65 break;
66 default:
67 create = false;
68 break;
69 }
70 }
71 }
72
73 if (create)
74 return new SystemRuntimeMacOSX (process);
75 return NULL;
76}
77
78//----------------------------------------------------------------------
79// Constructor
80//----------------------------------------------------------------------
81SystemRuntimeMacOSX::SystemRuntimeMacOSX (Process* process) :
82 SystemRuntime(process),
83 m_break_id(LLDB_INVALID_BREAK_ID),
84 m_mutex(Mutex::eMutexTypeRecursive)
85{
86 m_ldi_header.initialized = 0;
87}
88
89//----------------------------------------------------------------------
90// Destructor
91//----------------------------------------------------------------------
92SystemRuntimeMacOSX::~SystemRuntimeMacOSX()
93{
94 Clear (true);
95}
96
97//----------------------------------------------------------------------
98// Clear out the state of this class.
99//----------------------------------------------------------------------
100void
101SystemRuntimeMacOSX::Clear (bool clear_process)
102{
103 Mutex::Locker locker(m_mutex);
104
105 if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
106 m_process->ClearBreakpointSiteByID(m_break_id);
107
108 if (clear_process)
109 m_process = NULL;
110 m_break_id = LLDB_INVALID_BREAK_ID;
111 m_ldi_header.initialized = 0;
112}
113
114
115void
116SystemRuntimeMacOSX::DidAttach ()
117{
118}
119
120void
121SystemRuntimeMacOSX::DidLaunch ()
122{
123}
124
125void
126SystemRuntimeMacOSX::ModulesDidLoad (ModuleList &module_list)
127{
128}
129
130bool
131SystemRuntimeMacOSX::LdiHeadersInitialized ()
132{
133 ParseLdiHeaders();
134 return m_ldi_header.initialized;
135}
136
137void
138SystemRuntimeMacOSX::ParseLdiHeaders ()
139{
140 if (m_ldi_header.initialized)
141 return;
142 static ConstString ldi_header_symbol ("ldi_infos");
143 SymbolContextList sc_list;
144 if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType (ldi_header_symbol, eSymbolTypeData, sc_list) > 0)
145 {
146 SymbolContext sc;
147 sc_list.GetContextAtIndex (0, sc);
148 AddressRange addr_range;
149 sc.GetAddressRange (eSymbolContextSymbol, 0, false, addr_range);
150
151 Error error;
152 Address ldi_header_addr = addr_range.GetBaseAddress();
153 uint8_t version_buf[6]; // version, ldi_header_size, initialized fields
154 DataExtractor data (version_buf, sizeof(version_buf), m_process->GetByteOrder(), m_process->GetAddressByteSize());
155 const size_t count = sizeof (version_buf);
156 const bool prefer_file_cache = false;
157 if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, version_buf, count, error) == sizeof (version_buf))
158 {
159 int version, initialized, ldi_header_size;
160 offset_t offset = 0;
161 version = data.GetU16(&offset);
162 ldi_header_size = data.GetU16(&offset);
163 initialized = data.GetU16(&offset);
164 if (initialized)
165 {
166 DataBufferHeap ldi_header (ldi_header_size, 0);
167 DataExtractor ldi_extractor (ldi_header.GetBytes(), ldi_header.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
168 if (m_process->GetTarget().ReadMemory (ldi_header_addr, prefer_file_cache, ldi_header.GetBytes(), ldi_header.GetByteSize(), error) == ldi_header.GetByteSize())
169 {
170 offset = 0;
171 m_ldi_header.version = ldi_extractor.GetU16(&offset);
172 m_ldi_header.ldi_header_size = ldi_extractor.GetU16(&offset);
173 m_ldi_header.initialized = ldi_extractor.GetU16(&offset);
174 m_ldi_header.queue_size = ldi_extractor.GetU16(&offset);
175 m_ldi_header.item_size = ldi_extractor.GetU16(&offset);
176
177 // 6 bytes of padding here
178 offset += 6;
179
180 m_ldi_header.queues_head_ptr_address = ldi_extractor.GetU64(&offset);
181 m_ldi_header.items_head_ptr_address = ldi_extractor.GetU64(&offset);
182
183 m_ldi_header.queue_offsets.next = ldi_extractor.GetU16(&offset);
184 m_ldi_header.queue_offsets.prev = ldi_extractor.GetU16(&offset);
185 m_ldi_header.queue_offsets.queue_id = ldi_extractor.GetU16(&offset);
186 m_ldi_header.queue_offsets.current_item_ptr = ldi_extractor.GetU16(&offset);
187
188 m_ldi_header.item_offsets.next = ldi_extractor.GetU16(&offset);
189 m_ldi_header.item_offsets.prev = ldi_extractor.GetU16(&offset);
190 m_ldi_header.item_offsets.type = ldi_extractor.GetU16(&offset);
191 m_ldi_header.item_offsets.identifier = ldi_extractor.GetU16(&offset);
192 m_ldi_header.item_offsets.stop_id = ldi_extractor.GetU16(&offset);
193 m_ldi_header.item_offsets.backtrace_length = ldi_extractor.GetU16(&offset);
194 m_ldi_header.item_offsets.backtrace_ptr = ldi_extractor.GetU16(&offset);
195 m_ldi_header.item_offsets.thread_name_ptr = ldi_extractor.GetU16(&offset);
196 m_ldi_header.item_offsets.queue_name_ptr = ldi_extractor.GetU16(&offset);
197 m_ldi_header.item_offsets.unique_thread_id = ldi_extractor.GetU16(&offset);
198 m_ldi_header.item_offsets.pthread_id = ldi_extractor.GetU16(&offset);
199 m_ldi_header.item_offsets.enqueueing_thread_dispatch_queue_t = ldi_extractor.GetU16(&offset);
200 m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr = ldi_extractor.GetU16(&offset);
Jason Molendaa6e91302013-11-19 05:44:41 +0000201
202 if (ldi_header.GetByteSize () > offset)
203 {
204 m_ldi_header.item_offsets.queue_id_from_thread_info = ldi_extractor.GetU16(&offset);
205 }
206 else
207 {
208 m_ldi_header.item_offsets.queue_id_from_thread_info = 0xffff;
209 }
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000210 }
211 }
212 }
213 }
214}
215
216lldb::addr_t
217SystemRuntimeMacOSX::GetQueuesHead ()
218{
219 if (!LdiHeadersInitialized())
220 return LLDB_INVALID_ADDRESS;
221
222 Error error;
223 addr_t queues_head = m_process->ReadPointerFromMemory (m_ldi_header.queues_head_ptr_address, error);
224 if (error.Success() == false || queues_head == LLDB_INVALID_ADDRESS || queues_head == 0)
225 return LLDB_INVALID_ADDRESS;
226
227 return queues_head;
228}
229
230lldb::addr_t
231SystemRuntimeMacOSX::GetItemsHead ()
232{
233 if (!LdiHeadersInitialized())
234 return LLDB_INVALID_ADDRESS;
235
236 Error error;
237 addr_t items_head = m_process->ReadPointerFromMemory (m_ldi_header.items_head_ptr_address, error);
238 if (error.Success() == false || items_head == LLDB_INVALID_ADDRESS || items_head == 0)
239 return LLDB_INVALID_ADDRESS;
240
241 return items_head;
242}
243
244addr_t
245SystemRuntimeMacOSX::GetThreadCreatorItem (ThreadSP thread_sp)
246{
247 addr_t enqueued_item_ptr = thread_sp->GetExtendedBacktraceToken();
248 if (enqueued_item_ptr == LLDB_INVALID_ADDRESS)
249 {
250 if (thread_sp->GetQueueID() == LLDB_INVALID_QUEUE_ID || thread_sp->GetQueueID() == 0)
251 return LLDB_INVALID_ADDRESS;
252
253 Error error;
254 uint64_t this_thread_queue_id = thread_sp->GetQueueID();
255
256 addr_t queues_head = GetQueuesHead();
257 if (queues_head == LLDB_INVALID_ADDRESS)
258 return LLDB_INVALID_ADDRESS;
259
260 // Step through the queues_head linked list looking for a queue matching this thread, if any
261 uint64_t queue_obj_ptr = queues_head;
262 enqueued_item_ptr = LLDB_INVALID_ADDRESS;
263
264 while (queue_obj_ptr != 0)
265 {
266 uint64_t queue_id = m_process->ReadUnsignedIntegerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.queue_id, 8, LLDB_INVALID_ADDRESS, error);
267 if (error.Success() && queue_id != LLDB_INVALID_ADDRESS)
268 {
269 if (queue_id == this_thread_queue_id)
270 {
271 enqueued_item_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.current_item_ptr, error);
272 break;
273 }
274 }
275 queue_obj_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.next, error);
276 if (error.Success() == false || queue_obj_ptr == LLDB_INVALID_ADDRESS)
277 {
278 break;
279 }
280 }
281 }
282
283 return enqueued_item_ptr;
284}
285
286SystemRuntimeMacOSX::ArchivedBacktrace
287SystemRuntimeMacOSX::GetLibdispatchExtendedBacktrace (ThreadSP thread_sp)
288{
289 ArchivedBacktrace bt;
290 bt.stop_id = 0;
291 bt.stop_id_is_valid = false;
292 bt.libdispatch_queue_id = LLDB_INVALID_QUEUE_ID;
293
294 addr_t enqueued_item_ptr = GetThreadCreatorItem (thread_sp);
295
296 if (enqueued_item_ptr == LLDB_INVALID_ADDRESS)
297 return bt;
298
299 Error error;
300 uint32_t ptr_size = m_process->GetTarget().GetArchitecture().GetAddressByteSize();
301
302 uint32_t backtrace_length = m_process->ReadUnsignedIntegerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.backtrace_length, 4, 0, error);
303 addr_t pc_array_address = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.backtrace_ptr, error);
304
305 if (backtrace_length == 0 || pc_array_address == LLDB_INVALID_ADDRESS)
306 return bt;
307
308 for (uint32_t idx = 0; idx < backtrace_length; idx++)
309 {
310 addr_t pc_val = m_process->ReadPointerFromMemory (pc_array_address + (ptr_size * idx), error);
311 if (error.Success() && pc_val != LLDB_INVALID_ADDRESS)
312 {
313 bt.pcs.push_back (pc_val);
314 }
315 }
316
317 return bt;
318}
319
320const std::vector<ConstString> &
321SystemRuntimeMacOSX::GetExtendedBacktraceTypes ()
322{
323 if (m_types.size () == 0)
324 {
325 m_types.push_back(ConstString("libdispatch"));
326 m_types.push_back(ConstString("pthread"));
327 }
328 return m_types;
329}
330
331void
332SystemRuntimeMacOSX::SetNewThreadQueueName (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
333{
334 addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
335
336 if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
337 {
338 Error error;
339 addr_t queue_name_ptr = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.queue_name_ptr, error);
340 if (queue_name_ptr != LLDB_INVALID_ADDRESS && error.Success())
341 {
Jason Molenda8ee9cb52013-11-16 01:24:22 +0000342 char namebuf[512];
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000343 if (m_process->ReadCStringFromMemory (queue_name_ptr, namebuf, sizeof (namebuf), error) > 0 && error.Success())
344 {
345 new_extended_thread_sp->SetQueueName (namebuf);
346 }
347 }
348 }
349}
350
351void
Jason Molenda8ee9cb52013-11-16 01:24:22 +0000352SystemRuntimeMacOSX::SetNewThreadThreadName (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
353{
354 addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
355
356 if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
357 {
358 Error error;
359 addr_t thread_name_ptr = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.thread_name_ptr, error);
360 if (thread_name_ptr != LLDB_INVALID_ADDRESS && error.Success())
361 {
362 char namebuf[512];
363 if (m_process->ReadCStringFromMemory (thread_name_ptr, namebuf, sizeof (namebuf), error) > 0 && error.Success())
364 {
365 new_extended_thread_sp->SetName (namebuf);
366 }
367 }
368 }
369}
370
371
372void
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000373SystemRuntimeMacOSX::SetNewThreadExtendedBacktraceToken (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
374{
375 addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
376 if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
377 {
378 Error error;
379 uint64_t further_extended_backtrace = m_process->ReadPointerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.enqueueing_thread_dispatch_block_ptr, error);
380 if (error.Success() && further_extended_backtrace != 0 && further_extended_backtrace != LLDB_INVALID_ADDRESS)
381 {
382 new_extended_thread_sp->SetExtendedBacktraceToken (further_extended_backtrace);
383 }
384 }
385}
386
Jason Molendaa6e91302013-11-19 05:44:41 +0000387void
388SystemRuntimeMacOSX::SetNewThreadQueueID (ThreadSP original_thread_sp, ThreadSP new_extended_thread_sp)
389{
390 queue_id_t queue_id = LLDB_INVALID_QUEUE_ID;
391 addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
392 if (enqueued_item_ptr != LLDB_INVALID_ADDRESS && m_ldi_header.item_offsets.queue_id_from_thread_info != 0xffff)
393 {
394 Error error;
395 queue_id = m_process->ReadUnsignedIntegerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.queue_id_from_thread_info, 8, LLDB_INVALID_QUEUE_ID, error);
396 if (!error.Success())
397 queue_id = LLDB_INVALID_QUEUE_ID;
398 }
399
400 if (queue_id != LLDB_INVALID_QUEUE_ID)
401 {
402 new_extended_thread_sp->SetQueueID (queue_id);
403 }
404}
405
406
Jason Molenda8ee9cb52013-11-16 01:24:22 +0000407lldb::tid_t
Jason Molendaa6e91302013-11-19 05:44:41 +0000408SystemRuntimeMacOSX::GetNewThreadUniqueThreadID (ThreadSP original_thread_sp)
Jason Molenda8ee9cb52013-11-16 01:24:22 +0000409{
410 tid_t ret = LLDB_INVALID_THREAD_ID;
411 addr_t enqueued_item_ptr = GetThreadCreatorItem (original_thread_sp);
412 if (enqueued_item_ptr != LLDB_INVALID_ADDRESS)
413 {
414 Error error;
415 ret = m_process->ReadUnsignedIntegerFromMemory (enqueued_item_ptr + m_ldi_header.item_offsets.unique_thread_id, 8, LLDB_INVALID_THREAD_ID, error);
416 if (!error.Success())
417 ret = LLDB_INVALID_THREAD_ID;
418 }
419 return ret;
420}
421
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000422ThreadSP
423SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP original_thread_sp, ConstString type)
424{
425 ThreadSP new_extended_thread_sp;
426
427 if (type != ConstString("libdispatch"))
428 return new_extended_thread_sp;
429
430 ArchivedBacktrace bt = GetLibdispatchExtendedBacktrace (original_thread_sp);
431
432 if (bt.pcs.size() == 0)
433 return new_extended_thread_sp;
434
Jason Molendaa6e91302013-11-19 05:44:41 +0000435 tid_t unique_thread_id = GetNewThreadUniqueThreadID (original_thread_sp);
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000436
Jason Molenda8ee9cb52013-11-16 01:24:22 +0000437 new_extended_thread_sp.reset (new HistoryThread (*m_process, unique_thread_id, bt.pcs, bt.stop_id, bt.stop_id_is_valid));
438
Jason Molendaa6e91302013-11-19 05:44:41 +0000439 SetNewThreadThreadName (original_thread_sp, new_extended_thread_sp);
440 SetNewThreadQueueName (original_thread_sp, new_extended_thread_sp);
441 SetNewThreadQueueID (original_thread_sp, new_extended_thread_sp);
442 SetNewThreadExtendedBacktraceToken (original_thread_sp, new_extended_thread_sp);
Jason Molendaa7b5afa2013-11-15 00:17:32 +0000443 return new_extended_thread_sp;
444}
445
446
447void
448SystemRuntimeMacOSX::Initialize()
449{
450 PluginManager::RegisterPlugin (GetPluginNameStatic(),
451 GetPluginDescriptionStatic(),
452 CreateInstance);
453}
454
455void
456SystemRuntimeMacOSX::Terminate()
457{
458 PluginManager::UnregisterPlugin (CreateInstance);
459}
460
461
462lldb_private::ConstString
463SystemRuntimeMacOSX::GetPluginNameStatic()
464{
465 static ConstString g_name("systemruntime-macosx");
466 return g_name;
467}
468
469const char *
470SystemRuntimeMacOSX::GetPluginDescriptionStatic()
471{
472 return "System runtime plugin for Mac OS X native libraries.";
473}
474
475
476//------------------------------------------------------------------
477// PluginInterface protocol
478//------------------------------------------------------------------
479lldb_private::ConstString
480SystemRuntimeMacOSX::GetPluginName()
481{
482 return GetPluginNameStatic();
483}
484
485uint32_t
486SystemRuntimeMacOSX::GetPluginVersion()
487{
488 return 1;
489}