ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstString type) { ThreadSP originating_thread_sp; if (BacktraceRecordingHeadersInitialized() && type == ConstString ("libdispatch")) { Error error; // real_thread is either an actual, live thread (in which case we need to call into // libBacktraceRecording to find its originator) or it is an extended backtrace itself, // in which case we get the token from it and call into libBacktraceRecording to find // the originator of that token. if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) { originating_thread_sp = GetExtendedBacktraceFromItemRef (real_thread->GetExtendedBacktraceToken()); } else { ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); 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); m_page_to_free = LLDB_INVALID_ADDRESS; m_page_to_free_size = 0; if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && ret.item_buffer_size > 0) { DataBufferHeap data (ret.item_buffer_size, 0); if (m_process->ReadMemory (ret.item_buffer_ptr, data.GetBytes(), ret.item_buffer_size, error) && error.Success()) { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize()); ItemInfo item = ExtractItemInfoFromBuffer (extractor); bool stop_id_is_valid = true; if (item.stop_id == 0) stop_id_is_valid = false; originating_thread_sp.reset (new HistoryThread (*m_process, item.enqueuing_thread_id, item.enqueuing_callstack, item.stop_id, stop_id_is_valid)); originating_thread_sp->SetExtendedBacktraceToken (item.item_that_enqueued_this); originating_thread_sp->SetQueueName (item.enqueuing_queue_label.c_str()); originating_thread_sp->SetQueueID (item.enqueuing_queue_serialnum); // originating_thread_sp->SetThreadName (item.enqueuing_thread_label.c_str()); } m_page_to_free = ret.item_buffer_ptr; m_page_to_free_size = ret.item_buffer_size; } } } return originating_thread_sp; }
addr_t SystemRuntimeMacOSX::GetThreadCreatorItem (ThreadSP thread_sp) { addr_t enqueued_item_ptr = thread_sp->GetExtendedBacktraceToken(); if (enqueued_item_ptr == LLDB_INVALID_ADDRESS) { if (thread_sp->GetQueueID() == LLDB_INVALID_QUEUE_ID || thread_sp->GetQueueID() == 0) return LLDB_INVALID_ADDRESS; Error error; uint64_t this_thread_queue_id = thread_sp->GetQueueID(); addr_t queues_head = GetQueuesHead(); if (queues_head == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; // Step through the queues_head linked list looking for a queue matching this thread, if any uint64_t queue_obj_ptr = queues_head; enqueued_item_ptr = LLDB_INVALID_ADDRESS; while (queue_obj_ptr != 0) { uint64_t queue_id = m_process->ReadUnsignedIntegerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.queue_id, 8, LLDB_INVALID_ADDRESS, error); if (error.Success() && queue_id != LLDB_INVALID_ADDRESS) { if (queue_id == this_thread_queue_id) { enqueued_item_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.current_item_ptr, error); break; } } queue_obj_ptr = m_process->ReadPointerFromMemory (queue_obj_ptr + m_ldi_header.queue_offsets.next, error); if (error.Success() == false || queue_obj_ptr == LLDB_INVALID_ADDRESS) { break; } } } return enqueued_item_ptr; }