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