libBacktraceRecording __introspection_dispatch_queue_get_pending_items is

changing the data it returns; this change accepts either the old format or
the new format.  It doesn't yet benefit from the new format's additions -
but I need to get this checked in so we aren't rev-locked.
Also add a missing .i entry for SBQueue::GetNumRunningItems() missing from
the last checkin.
<rdar://problem/16272115> 

llvm-svn: 203421
This commit is contained in:
Jason Molenda 2014-03-09 21:17:08 +00:00
parent fe95dc95b5
commit 37e9b5ab38
5 changed files with 115 additions and 51 deletions

View File

@ -38,7 +38,7 @@ class QueueItem :
{
public:
QueueItem (lldb::QueueSP queue_sp);
QueueItem (lldb::QueueSP queue_sp, lldb::addr_t item_ref);
~QueueItem ();
@ -222,6 +222,7 @@ protected:
lldb::QueueItemKind m_kind;
lldb_private::Address m_address;
lldb::addr_t m_item_ref; // the token we can be used to fetch more information about this queue item
lldb::addr_t m_item_that_enqueued_this_ref; // a handle that we can pass into libBacktraceRecording
// to get the QueueItem that enqueued this item
lldb::tid_t m_enqueueing_thread_id; // thread that enqueued this item

View File

@ -48,6 +48,9 @@ public:
lldb::SBQueueItem
GetPendingItemAtIndex (uint32_t);
uint32_t
GetNumRunningItems ();
};
} // namespace lldb

View File

@ -526,18 +526,104 @@ SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
}
}
// 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().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 && 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 && 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())
{
std::vector<addr_t> pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
for (addr_t pending_item : pending_item_refs)
PendingItemsForQueue pending_item_refs = GetPendingItemRefsForQueue (queue->GetLibdispatchQueueAddress());
for (ItemRefAndCodeAddress pending_item : pending_item_refs.item_refs_and_code_addresses)
{
AppleGetItemInfoHandler::GetItemInfoReturnInfo ret;
ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread());
Error error;
ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), pending_item, m_page_to_free, m_page_to_free_size, error);
ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), pending_item.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)
@ -547,7 +633,7 @@ SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
{
DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
ItemInfo item = ExtractItemInfoFromBuffer (extractor);
QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this()));
QueueItemSP queue_item_sp (new QueueItem (queue->shared_from_this(), pending_item.item_ref));
queue_item_sp->SetItemThatEnqueuedThis (item.item_that_enqueued_this);
Address addr;
@ -573,50 +659,6 @@ SystemRuntimeMacOSX::PopulatePendingItemsForQueue (Queue *queue)
}
}
// Returns an array of introspection_dispatch_item_info_ref's 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.
std::vector<lldb::addr_t>
SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue)
{
std::vector<addr_t> 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))
{
offset_t offset = 0;
DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize());
int i = 0;
while (offset < pending_items_pointer.items_buffer_size && i < pending_items_pointer.count)
{
pending_item_refs.push_back (extractor.GetPointer (&offset));
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::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size,
uint64_t count, lldb_private::QueueList &queue_list)

View File

@ -188,6 +188,23 @@ private:
}
};
// The libBacktraceRecording function __introspection_dispatch_queue_get_pending_items has
// two forms. It can either return a simple array of item_refs (void *) size or it can return
// a header with uint32_t version, a uint32_t size of item, and then an array of item_refs (void*)
// and code addresses (void*) for all the pending blocks.
struct ItemRefAndCodeAddress {
lldb::addr_t item_ref;
lldb::addr_t code_address;
};
struct PendingItemsForQueue {
bool new_style; // new-style means both item_refs and code_addresses avail
// old-style means only item_refs is filled in
std::vector<ItemRefAndCodeAddress> item_refs_and_code_addresses;
};
bool
BacktraceRecordingHeadersInitialized ();
@ -197,7 +214,7 @@ private:
void
ReadLibdispatchOffsets ();
std::vector<lldb::addr_t>
PendingItemsForQueue
GetPendingItemRefsForQueue (lldb::addr_t queue);
ItemInfo

View File

@ -15,10 +15,11 @@
using namespace lldb;
using namespace lldb_private;
QueueItem::QueueItem (QueueSP queue_sp) :
QueueItem::QueueItem (QueueSP queue_sp, lldb::addr_t item_ref) :
m_queue_wp (),
m_kind (eQueueItemKindUnknown),
m_address (),
m_item_ref (item_ref),
m_item_that_enqueued_this_ref (LLDB_INVALID_ADDRESS),
m_enqueueing_thread_id (LLDB_INVALID_THREAD_ID),
m_enqueueing_queue_id (LLDB_INVALID_QUEUE_ID),