diff options
Diffstat (limited to 'source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp')
-rw-r--r-- | source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 1021 |
1 files changed, 0 insertions, 1021 deletions
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp deleted file mode 100644 index e61f04e489e8..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ /dev/null @@ -1,1021 +0,0 @@ -//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Plugins/Process/Utility/HistoryThread.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessStructReader.h" -#include "lldb/Target/Queue.h" -#include "lldb/Target/QueueList.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -#include "SystemRuntimeMacOSX.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) { - bool create = false; - if (!create) { - create = true; - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - create = (object_file->GetStrata() == ObjectFile::eStrataUser); - } - } - - if (create) { - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - create = triple_ref.getVendor() == llvm::Triple::Apple; - break; - default: - create = false; - break; - } - } - } - - if (create) - return new SystemRuntimeMacOSX(process); - return NULL; -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process) - : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(), - m_get_queues_handler(process), m_get_pending_items_handler(process), - m_get_item_info_handler(process), m_get_thread_item_info_handler(process), - m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0), - m_lib_backtrace_recording_info(), - m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_offsets(), - m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS), - m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_tsd_indexes(), - m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_voucher_offsets() {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); } - -void SystemRuntimeMacOSX::Detach() { - m_get_queues_handler.Detach(); - m_get_pending_items_handler.Detach(); - m_get_item_info_handler.Detach(); - m_get_thread_item_info_handler.Detach(); -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void SystemRuntimeMacOSX::Clear(bool clear_process) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->ClearBreakpointSiteByID(m_break_id); - - if (clear_process) - m_process = NULL; - m_break_id = LLDB_INVALID_BREAK_ID; -} - -std::string -SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) { - std::string dispatch_queue_name; - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return ""; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - addr_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - if (m_libdispatch_offsets.dqo_version >= 4) { - // libdispatch versions 4+, pointer to dispatch name is in the queue - // structure. - addr_t pointer_to_label_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - addr_t label_addr = - m_process->ReadPointerFromMemory(pointer_to_label_address, error); - if (error.Success()) { - m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name, - error); - } - } else { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - addr_t label_addr = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0'); - size_t bytes_read = - m_process->ReadMemory(label_addr, &dispatch_queue_name[0], - m_libdispatch_offsets.dqo_label_size, error); - if (bytes_read < m_libdispatch_offsets.dqo_label_size) - dispatch_queue_name.erase(bytes_read); - } - } - } - return dispatch_queue_name; -} - -lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress( - addr_t dispatch_qaddr) { - addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - Status error; - libdispatch_queue_t_address = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (!error.Success()) { - libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - } - return libdispatch_queue_t_address; -} - -lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) { - if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0) - return eQueueKindUnknown; - - QueueKind kind = eQueueKindUnknown; - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid() && - m_libdispatch_offsets.dqo_version >= 4) { - Status error; - uint64_t width = m_process->ReadUnsignedIntegerFromMemory( - dispatch_queue_addr + m_libdispatch_offsets.dqo_width, - m_libdispatch_offsets.dqo_width_size, 0, error); - if (error.Success()) { - if (width == 1) { - kind = eQueueKindSerial; - } - if (width > 1) { - kind = eQueueKindConcurrent; - } - } - } - return kind; -} - -void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints( - lldb_private::StructuredData::ObjectSP dict_sp) { - StructuredData::Dictionary *dict = dict_sp->GetAsDictionary(); - if (dict) { - ReadLibpthreadOffsets(); - if (m_libpthread_offsets.IsValid()) { - dict->AddIntegerItem("plo_pthread_tsd_base_offset", - m_libpthread_offsets.plo_pthread_tsd_base_offset); - dict->AddIntegerItem( - "plo_pthread_tsd_base_address_offset", - m_libpthread_offsets.plo_pthread_tsd_base_address_offset); - dict->AddIntegerItem("plo_pthread_tsd_entry_size", - m_libpthread_offsets.plo_pthread_tsd_entry_size); - } - - ReadLibdispatchTSDIndexes(); - if (m_libdispatch_tsd_indexes.IsValid()) { - dict->AddIntegerItem("dti_queue_index", - m_libdispatch_tsd_indexes.dti_queue_index); - dict->AddIntegerItem("dti_voucher_index", - m_libdispatch_tsd_indexes.dti_voucher_index); - dict->AddIntegerItem("dti_qos_class_index", - m_libdispatch_tsd_indexes.dti_qos_class_index); - } - } -} - -bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) { - if (thread_sp && thread_sp->GetStackFrameCount() > 0 && - thread_sp->GetFrameWithConcreteFrameIndex(0)) { - const SymbolContext sym_ctx( - thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext( - eSymbolContextSymbol)); - static ConstString g_select_symbol("__select"); - if (sym_ctx.GetFunctionName() == g_select_symbol) { - return false; - } - } - return true; -} - -lldb::queue_id_t -SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) { - queue_id_t queue_id = LLDB_INVALID_QUEUE_ID; - - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return queue_id; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - uint64_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - addr_t serialnum_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum; - queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory( - serialnum_address, m_libdispatch_offsets.dqo_serialnum_size, - LLDB_INVALID_QUEUE_ID, error); - if (error.Success()) { - queue_id = serialnum; - } - } - } - - return queue_id; -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() { - if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_dispatch_queue_offsets_symbol_name( - "dispatch_queue_offsets"); - const Symbol *dispatch_queue_offsets_symbol = NULL; - - // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 - // ("Snow Leopard") - ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libSystem_module_spec)); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - - // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") - // and later - if (dispatch_queue_offsets_symbol == NULL) { - ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib")); - module_sp = m_process->GetTarget().GetImages().FindFirstModule( - libdispatch_module_spec); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - } - if (dispatch_queue_offsets_symbol) - m_dispatch_queue_offsets_addr = - dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget()); -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsets() { - if (m_libdispatch_offsets.IsValid()) - return; - - ReadLibdispatchOffsetsAddress(); - - uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - Status error; - if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibdispatchOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version, - sizeof(struct LibdispatchOffsets) / sizeof(uint16_t)); - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() { - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libpthread_layout_offsets_symbol_name( - "pthread_layout_offsets"); - const Symbol *libpthread_layout_offsets_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libpthread_layout_offsets_symbol = - module_sp->FindFirstSymbolWithNameAndType( - g_libpthread_layout_offsets_symbol_name, eSymbolTypeData); - if (libpthread_layout_offsets_symbol) { - m_libpthread_layout_offsets_addr = - libpthread_layout_offsets_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsets() { - if (m_libpthread_offsets.IsValid()) - return; - - ReadLibpthreadOffsetsAddress(); - - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) { - uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - Status error; - if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibpthreadOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libpthread_offsets.plo_version, - sizeof(struct LibpthreadOffsets) / sizeof(uint16_t)); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() { - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libdispatch_tsd_indexes_symbol_name( - "dispatch_tsd_indexes"); - const Symbol *libdispatch_tsd_indexes_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData); - if (libdispatch_tsd_indexes_symbol) { - m_dispatch_tsd_indexes_addr = - libdispatch_tsd_indexes_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() { - if (m_libdispatch_tsd_indexes.IsValid()) - return; - - ReadLibdispatchTSDIndexesAddress(); - - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - -// We don't need to check the version number right now, it will be at least 2, -// but keep this code around to fetch just the version # for the future where -// we need to fetch alternate versions of the struct. -#if 0 - uint16_t dti_version = 2; - Address dti_struct_addr; - if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr)) - { - Status error; - uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error); - if (error.Success() && dti_version != UINT16_MAX) - { - dti_version = version; - } - } -#endif - - ClangASTContext *ast_ctx = - m_process->GetTarget().GetScratchClangASTContext(); - if (ast_ctx->getASTContext() && - m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - CompilerType uint16 = - ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); - CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType( - nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", - clang::TTK_Struct, lldb::eLanguageTypeC); - - ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_version", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_queue_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_voucher_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_qos_class_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s); - - ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr, - dispatch_tsd_indexes_s); - - m_libdispatch_tsd_indexes.dti_version = - struct_reader.GetField<uint16_t>(ConstString("dti_version")); - m_libdispatch_tsd_indexes.dti_queue_index = - struct_reader.GetField<uint16_t>(ConstString("dti_queue_index")); - m_libdispatch_tsd_indexes.dti_voucher_index = - struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index")); - m_libdispatch_tsd_indexes.dti_qos_class_index = - struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index")); - } - } -} - -ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread, - ConstString type) { - ThreadSP originating_thread_sp; - if (BacktraceRecordingHeadersInitialized() && - type == ConstString("libdispatch")) { - Status 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().GetExpressionExecutionThread()); - 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; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) { - ThreadSP return_thread_sp; - - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - 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; - return_thread_sp.reset(new HistoryThread( - *m_process, item.enqueuing_thread_id, item.enqueuing_callstack, - item.stop_id, stop_id_is_valid)); - return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this); - return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str()); - return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum); - // return_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 return_thread_sp; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp, - ConstString type) { - ThreadSP extended_thread_sp; - if (type != ConstString("libdispatch")) - return extended_thread_sp; - - bool stop_id_is_valid = true; - if (queue_item_sp->GetStopID() == 0) - stop_id_is_valid = false; - - extended_thread_sp.reset( - new HistoryThread(*m_process, queue_item_sp->GetEnqueueingThreadID(), - queue_item_sp->GetEnqueueingBacktrace(), - queue_item_sp->GetStopID(), stop_id_is_valid)); - extended_thread_sp->SetExtendedBacktraceToken( - queue_item_sp->GetItemThatEnqueuedThis()); - extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str()); - extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID()); - // extended_thread_sp->SetThreadName - // (queue_item_sp->GetThreadLabel().c_str()); - - return extended_thread_sp; -} - -/* Returns true if we were able to get the version / offset information - * out of libBacktraceRecording. false means we were unable to retrieve - * this; the queue_info_version field will be 0. - */ - -bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() { - if (m_lib_backtrace_recording_info.queue_info_version != 0) - return true; - - addr_t queue_info_version_address = LLDB_INVALID_ADDRESS; - addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS; - addr_t item_info_version_address = LLDB_INVALID_ADDRESS; - addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS; - Target &target = m_process->GetTarget(); - - static ConstString introspection_dispatch_queue_info_version( - "__introspection_dispatch_queue_info_version"); - SymbolContextList sc_list; - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_queue_info_data_offset( - "__introspection_dispatch_queue_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_version( - "__introspection_dispatch_item_info_version"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_data_offset( - "__introspection_dispatch_item_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - - if (queue_info_version_address != LLDB_INVALID_ADDRESS && - queue_info_data_offset_address != LLDB_INVALID_ADDRESS && - item_info_version_address != LLDB_INVALID_ADDRESS && - item_info_data_offset_address != LLDB_INVALID_ADDRESS) { - Status error; - m_lib_backtrace_recording_info.queue_info_version = - m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2, - 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.queue_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - queue_info_data_offset_address, 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_version = - m_process->ReadUnsignedIntegerFromMemory(item_info_version_address, - 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - item_info_data_offset_address, 2, 0, error); - if (!error.Success()) { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } - } - - return m_lib_backtrace_recording_info.queue_info_version != 0; -} - -const std::vector<ConstString> & -SystemRuntimeMacOSX::GetExtendedBacktraceTypes() { - if (m_types.size() == 0) { - m_types.push_back(ConstString("libdispatch")); - // We could have pthread as another type in the future if we have a way of - // gathering that information & it's useful to distinguish between them. - } - return m_types; -} - -void SystemRuntimeMacOSX::PopulateQueueList( - lldb_private::QueueList &queue_list) { - if (BacktraceRecordingHeadersInitialized()) { - AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - queue_info_pointer = m_get_queues_handler.GetCurrentQueues( - *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - - if (queue_info_pointer.count > 0 && - queue_info_pointer.queues_buffer_size > 0 && - queue_info_pointer.queues_buffer_ptr != 0 && - queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) { - PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr, - queue_info_pointer.queues_buffer_size, - queue_info_pointer.count, queue_list); - } - } - } - } - - // We either didn't have libBacktraceRecording (and need to create the queues - // list based on threads) or we did get the queues list from - // libBacktraceRecording but some special queues may not be included in its - // information. This is needed because libBacktraceRecording will only list - // queues with pending or running items by default - but the magic com.apple - // .main-thread queue on thread 1 is always around. - - for (ThreadSP thread_sp : m_process->Threads()) { - if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) { - if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) { - if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == NULL) { - QueueSP queue_sp(new Queue(m_process->shared_from_this(), - thread_sp->GetQueueID(), - thread_sp->GetQueueName())); - if (thread_sp->ThreadHasQueueInformation()) { - queue_sp->SetKind(thread_sp->GetQueueKind()); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } else { - queue_sp->SetKind( - GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress())); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } - } - } - } - } -} - -// Returns either an array of introspection_dispatch_item_info_ref's for the -// pending items on a queue or an array introspection_dispatch_item_info_ref's -// and code addresses for the pending items on a queue. The information about -// each of these pending items then needs to be fetched individually by passing -// the ref to libBacktraceRecording. - -SystemRuntimeMacOSX::PendingItemsForQueue -SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) { - PendingItemsForQueue pending_item_refs; - AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - pending_items_pointer = m_get_pending_items_handler.GetPendingItems( - *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - if (pending_items_pointer.count > 0 && - pending_items_pointer.items_buffer_size > 0 && - pending_items_pointer.items_buffer_ptr != 0 && - pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) { - DataBufferHeap data(pending_items_pointer.items_buffer_size, 0); - if (m_process->ReadMemory( - pending_items_pointer.items_buffer_ptr, data.GetBytes(), - pending_items_pointer.items_buffer_size, error)) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - // We either have an array of - // void* item_ref - // (old style) or we have a structure returned which looks like - // - // struct introspection_dispatch_pending_item_info_s { - // void *item_ref; - // void *function_or_block; - // }; - // - // struct introspection_dispatch_pending_items_array_s { - // uint32_t version; - // uint32_t size_of_item_info; - // introspection_dispatch_pending_item_info_s items[]; - // } - - offset_t offset = 0; - int i = 0; - uint32_t version = extractor.GetU32(&offset); - if (version == 1) { - pending_item_refs.new_style = true; - uint32_t item_size = extractor.GetU32(&offset); - uint32_t start_of_array_offset = offset; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - offset = start_of_array_offset + (i * item_size); - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = extractor.GetPointer(&offset); - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } else { - offset = 0; - pending_item_refs.new_style = false; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = LLDB_INVALID_ADDRESS; - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } - } - m_page_to_free = pending_items_pointer.items_buffer_ptr; - m_page_to_free_size = pending_items_pointer.items_buffer_size; - } - } - } - return pending_item_refs; -} - -void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) { - if (BacktraceRecordingHeadersInitialized()) { - PendingItemsForQueue pending_item_refs = - GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress()); - for (ItemRefAndCodeAddress pending_item : - pending_item_refs.item_refs_and_code_addresses) { - Address addr; - m_process->GetTarget().ResolveLoadAddress(pending_item.code_address, - addr); - QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(), - m_process->shared_from_this(), - pending_item.item_ref, addr)); - queue->PushPendingQueueItem(queue_item_sp); - } - } -} - -void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item, - addr_t item_ref) { - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - 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); - queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this); - queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id); - queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum); - queue_item->SetStopID(item.stop_id); - queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack); - queue_item->SetThreadLabel(item.enqueuing_thread_label); - queue_item->SetQueueLabel(item.enqueuing_queue_label); - queue_item->SetTargetQueueLabel(item.target_queue_label); - } - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } -} - -void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR( - lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count, - lldb_private::QueueList &queue_list) { - Status error; - DataBufferHeap data(queues_buffer_size, 0); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size, - error) == queues_buffer_size && - error.Success()) { - // We've read the information out of inferior memory; free it on the next - // call we make - m_page_to_free = queues_buffer; - m_page_to_free_size = queues_buffer_size; - - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - offset_t offset = 0; - uint64_t queues_read = 0; - - // The information about the queues is stored in this format (v1): typedef - // struct introspection_dispatch_queue_info_s { - // uint32_t offset_to_next; - // dispatch_queue_t queue; - // uint64_t serialnum; // queue's serialnum in the process, as - // provided by libdispatch - // uint32_t running_work_items_count; - // uint32_t pending_work_items_count; - // - // char data[]; // Starting here, we have variable-length data: - // // char queue_label[]; - // } introspection_dispatch_queue_info_s; - - while (queues_read < count && offset < queues_buffer_size) { - offset_t start_of_this_item = offset; - - uint32_t offset_to_next = extractor.GetU32(&offset); - - offset += 4; // Skip over the 4 bytes of reserved space - addr_t queue = extractor.GetPointer(&offset); - uint64_t serialnum = extractor.GetU64(&offset); - uint32_t running_work_items_count = extractor.GetU32(&offset); - uint32_t pending_work_items_count = extractor.GetU32(&offset); - - // Read the first field of the variable length data - offset = start_of_this_item + - m_lib_backtrace_recording_info.queue_info_data_offset; - const char *queue_label = extractor.GetCStr(&offset); - if (queue_label == NULL) - queue_label = ""; - - offset_t start_of_next_item = start_of_this_item + offset_to_next; - offset = start_of_next_item; - - if (log) - 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); - - QueueSP queue_sp( - new Queue(m_process->shared_from_this(), serialnum, queue_label)); - queue_sp->SetNumRunningWorkItems(running_work_items_count); - queue_sp->SetNumPendingWorkItems(pending_work_items_count); - queue_sp->SetLibdispatchQueueAddress(queue); - queue_sp->SetKind(GetQueueKind(queue)); - queue_list.AddQueue(queue_sp); - queues_read++; - } - } -} - -SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer( - lldb_private::DataExtractor &extractor) { - ItemInfo item; - - offset_t offset = 0; - - item.item_that_enqueued_this = extractor.GetPointer(&offset); - item.function_or_block = extractor.GetPointer(&offset); - item.enqueuing_thread_id = extractor.GetU64(&offset); - item.enqueuing_queue_serialnum = extractor.GetU64(&offset); - item.target_queue_serialnum = extractor.GetU64(&offset); - item.enqueuing_callstack_frame_count = extractor.GetU32(&offset); - item.stop_id = extractor.GetU32(&offset); - - offset = m_lib_backtrace_recording_info.item_info_data_offset; - - for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) { - item.enqueuing_callstack.push_back(extractor.GetPointer(&offset)); - } - item.enqueuing_thread_label = extractor.GetCStr(&offset); - item.enqueuing_queue_label = extractor.GetCStr(&offset); - item.target_queue_label = extractor.GetCStr(&offset); - - return item; -} - -void SystemRuntimeMacOSX::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void SystemRuntimeMacOSX::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginNameStatic() { - static ConstString g_name("systemruntime-macosx"); - return g_name; -} - -const char *SystemRuntimeMacOSX::GetPluginDescriptionStatic() { - return "System runtime plugin for Mac OS X native libraries."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t SystemRuntimeMacOSX::GetPluginVersion() { return 1; } |