Basic infrastructure code to exploit malloc stack logging as available on Mac OS X to track the allocation history of pointers on the target process

llvm-svn: 139337
diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
index 316540f..245eb58 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/MachTask.cpp
@@ -31,6 +31,7 @@
 #include "DNBLog.h"
 #include "MachProcess.h"
 #include "DNBDataRef.h"
+#include "stack_logging.h"
 
 #if defined (__arm__)
 
@@ -677,3 +678,86 @@
     return false;
 }
 
+static void foundStackLog(mach_stack_logging_record_t record, void *context) {
+    *((bool*)context) = true;
+}
+
+bool
+MachTask::HasMallocLoggingEnabled ()
+{
+    bool found = false;
+    
+    __mach_stack_logging_enumerate_records(m_task, 0x0, foundStackLog, &found);
+    return found;
+}
+
+struct history_enumerator_impl_data
+{
+    MachMallocEvent *buffer;
+    uint32_t        *position;
+    uint32_t         count;
+};
+
+static void history_enumerator_impl(mach_stack_logging_record_t record, void* enum_obj)
+{
+    history_enumerator_impl_data *data = (history_enumerator_impl_data*)enum_obj;
+    
+    if (*data->position >= data->count)
+        return;
+    
+    data->buffer[*data->position].m_base_address = record.address;
+    data->buffer[*data->position].m_size = record.argument;
+    data->buffer[*data->position].m_event_id = record.stack_identifier;
+    data->buffer[*data->position].m_event_type = record.type_flags == stack_logging_type_alloc ?   eMachMallocEventTypeAlloc :
+                                                 record.type_flags == stack_logging_type_dealloc ? eMachMallocEventTypeDealloc :
+                                                                                                   eMachMallocEventTypeOther;
+    *data->position+=1;
+}
+
+bool
+MachTask::EnumerateMallocRecords (MachMallocEvent *event_buffer,
+                                  uint32_t buffer_size,
+                                  uint32_t *count)
+{
+    return EnumerateMallocRecords(0,
+                                  event_buffer,
+                                  buffer_size,
+                                  count);
+}
+
+bool
+MachTask::EnumerateMallocRecords (mach_vm_address_t address,
+                                  MachMallocEvent *event_buffer,
+                                  uint32_t buffer_size,
+                                  uint32_t *count)
+{
+    if (!event_buffer || !count)
+        return false;
+    
+    if (buffer_size == 0)
+        return false;
+    
+    *count = 0;
+    history_enumerator_impl_data data = { event_buffer, count, buffer_size };
+    __mach_stack_logging_enumerate_records(m_task, address, history_enumerator_impl, &data);
+    return (*count > 0);
+}
+
+bool
+MachTask::EnumerateMallocFrames (MachMallocEventId event_id,
+                                 mach_vm_address_t *function_addresses_buffer,
+                                 uint32_t buffer_size,
+                                 uint32_t *count)
+{
+    if (!function_addresses_buffer || !count)
+        return false;
+    
+    if (buffer_size == 0)
+        return false;
+    
+    __mach_stack_logging_frames_for_uniqued_stack(m_task, event_id, &function_addresses_buffer[0], buffer_size, count);
+    *count -= 1;
+    if (function_addresses_buffer[*count-1] < vm_page_size)
+        *count -= 1;
+    return (*count > 0);
+}