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