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