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