Пример #1
0
void
SystemRuntimeMacOSX::CompleteQueueItem (QueueItem *queue_item, addr_t item_ref)
{
    AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;

    ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
    Error 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;
    }
}
bool
ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr)
{
    size_t size = sizeof(uint32_t)  // uint32_t entsize;
    + sizeof(uint32_t); // uint32_t count;
    
    DataBufferHeap buffer (size, '\0');
    Error error;
    
    process->ReadMemory(addr, buffer.GetBytes(), size, error);
    if (error.Fail())
    {
        return false;
    }
    
    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
    
    lldb::offset_t cursor = 0;
    
    m_entsize   = extractor.GetU32_unchecked(&cursor);
    m_count     = extractor.GetU32_unchecked(&cursor);
    m_first_ptr = addr + cursor;
    
    return true;
}
bool
ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr)
{
    size_t size = GetSize(process);
    
    DataBufferHeap buffer (size, '\0');
    Error error;
    
    process->ReadMemory(addr, buffer.GetBytes(), size, error);
    if (error.Fail())
    {
        return false;
    }
    
    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
    
    lldb::offset_t cursor = 0;
    
    m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
    m_types_ptr  = extractor.GetAddress_unchecked(&cursor);
    m_imp_ptr    = extractor.GetAddress_unchecked(&cursor);
    
    const size_t buffer_size = 1024;
    size_t count;
    
    DataBufferHeap string_buf(buffer_size, 0);
    
    count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
    m_name.assign((char*)string_buf.GetBytes(), count);
    
    count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
    m_types.assign((char*)string_buf.GetBytes(), count);
    
    return true;
}
bool
ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr)
{
    size_t ptr_size = process->GetAddressByteSize();
    
    size_t size = sizeof(uint32_t)             // uint32_t flags;
    + sizeof(uint32_t)                         // uint32_t instanceStart;
    + sizeof(uint32_t)                         // uint32_t instanceSize;
    + (ptr_size == 8 ? sizeof(uint32_t) : 0)   // uint32_t reserved; // __LP64__ only
    + ptr_size                                 // const uint8_t *ivarLayout;
    + ptr_size                                 // const char *name;
    + ptr_size                                 // const method_list_t *baseMethods;
    + ptr_size                                 // const protocol_list_t *baseProtocols;
    + ptr_size                                 // const ivar_list_t *ivars;
    + ptr_size                                 // const uint8_t *weakIvarLayout;
    + ptr_size;                                // const property_list_t *baseProperties;
    
    DataBufferHeap buffer (size, '\0');
    Error error;
    
    process->ReadMemory(addr, buffer.GetBytes(), size, error);
    if (error.Fail())
    {
        return false;
    }
    
    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
    
    lldb::offset_t cursor = 0;
    
    m_flags             = extractor.GetU32_unchecked(&cursor);
    m_instanceStart     = extractor.GetU32_unchecked(&cursor);
    m_instanceSize      = extractor.GetU32_unchecked(&cursor);
    if (ptr_size == 8)
        m_reserved      = extractor.GetU32_unchecked(&cursor);
    else
        m_reserved      = 0;
    m_ivarLayout_ptr     = extractor.GetAddress_unchecked(&cursor);
    m_name_ptr           = extractor.GetAddress_unchecked(&cursor);
    m_baseMethods_ptr    = extractor.GetAddress_unchecked(&cursor);
    m_baseProtocols_ptr  = extractor.GetAddress_unchecked(&cursor);
    m_ivars_ptr          = extractor.GetAddress_unchecked(&cursor);
    m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
    m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
    
    DataBufferHeap name_buf(1024, '\0');
    
    process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
    
    if (error.Fail())
    {
        return false;
    }
    
    m_name.assign((char*)name_buf.GetBytes());
    
    return true;
}
Пример #5
0
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;
}
Пример #6
0
ThreadSP
SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref)
{
    ThreadSP return_thread_sp;

    AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
    ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
    Error 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;
}
bool
ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr)
{
    size_t ptr_size = process->GetAddressByteSize();
    
    size_t size = sizeof(uint32_t)  // uint32_t flags;
    + sizeof(uint32_t)  // uint32_t version;
    + ptr_size          // const class_ro_t *ro;
    + ptr_size          // union { method_list_t **method_lists; method_list_t *method_list; };
    + ptr_size          // struct chained_property_list *properties;
    + ptr_size          // const protocol_list_t **protocols;
    + ptr_size          // Class firstSubclass;
    + ptr_size;         // Class nextSiblingClass;
    
    DataBufferHeap buffer (size, '\0');
    Error error;
    
    process->ReadMemory(addr, buffer.GetBytes(), size, error);
    if (error.Fail())
    {
        return false;
    }
    
    DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
    
    lldb::offset_t cursor = 0;
    
    m_flags             = extractor.GetU32_unchecked(&cursor);
    m_version           = extractor.GetU32_unchecked(&cursor);
    m_ro_ptr            = extractor.GetAddress_unchecked(&cursor);
    m_method_list_ptr   = extractor.GetAddress_unchecked(&cursor);
    m_properties_ptr    = extractor.GetAddress_unchecked(&cursor);
    m_firstSubclass     = extractor.GetAddress_unchecked(&cursor);
    m_nextSiblingClass  = extractor.GetAddress_unchecked(&cursor);
    
    return true;
}
Пример #8
0
void
SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
        uint64_t count, lldb_private::QueueList &queue_list)
{
    Error 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++;
        }
    }
}
Пример #9
0
SystemRuntimeMacOSX::PendingItemsForQueue
SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
{
    PendingItemsForQueue pending_item_refs;
    AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer;
    ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
    if (cur_thread_sp)
    {
        Error 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;
}