summaryrefslogtreecommitdiffstats
path: root/lldb/examples/darwin/heap_find/heap/heap_find.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/examples/darwin/heap_find/heap/heap_find.cpp')
-rw-r--r--lldb/examples/darwin/heap_find/heap/heap_find.cpp1470
1 files changed, 655 insertions, 815 deletions
diff --git a/lldb/examples/darwin/heap_find/heap/heap_find.cpp b/lldb/examples/darwin/heap_find/heap/heap_find.cpp
index de896775e40..3567e559a6a 100644
--- a/lldb/examples/darwin/heap_find/heap/heap_find.cpp
+++ b/lldb/examples/darwin/heap_find/heap/heap_find.cpp
@@ -13,39 +13,41 @@
//
// (lldb) process load /path/to/libheap.dylib
//
-// Now you can use the "find_pointer_in_heap" and "find_cstring_in_heap"
+// Now you can use the "find_pointer_in_heap" and "find_cstring_in_heap"
// functions in the expression parser.
//
-// This will grep everything in all active allocation blocks and print and
+// This will grep everything in all active allocation blocks and print and
// malloc blocks that contain the pointer 0x112233000000:
//
// (lldb) expression find_pointer_in_heap (0x112233000000)
//
-// This will grep everything in all active allocation blocks and print and
+// This will grep everything in all active allocation blocks and print and
// malloc blocks that contain the C string "hello" (as a substring, no
// NULL termination included):
//
// (lldb) expression find_cstring_in_heap ("hello")
//
-// The results will be printed to the STDOUT of the inferior program. The
-// return value of the "find_pointer_in_heap" function is the number of
+// The results will be printed to the STDOUT of the inferior program. The
+// return value of the "find_pointer_in_heap" function is the number of
// pointer references that were found. A quick example shows
//
// (lldb) expr find_pointer_in_heap(0x0000000104000410)
// (uint32_t) $5 = 0x00000002
-// 0x104000740: 0x0000000104000410 found in malloc block 0x104000730 + 16 (malloc_size = 48)
-// 0x100820060: 0x0000000104000410 found in malloc block 0x100820000 + 96 (malloc_size = 4096)
+// 0x104000740: 0x0000000104000410 found in malloc block 0x104000730 + 16
+// (malloc_size = 48)
+// 0x100820060: 0x0000000104000410 found in malloc block 0x100820000 + 96
+// (malloc_size = 4096)
//
// From the above output we see that 0x104000410 was found in the malloc block
// at 0x104000730 and 0x100820000. If we want to see what these blocks are, we
-// can display the memory for this block using the "address" ("A" for short)
+// can display the memory for this block using the "address" ("A" for short)
// format. The address format shows pointers, and if those pointers point to
// objects that have symbols or know data contents, it will display information
// about the pointers:
//
-// (lldb) memory read --format address --count 1 0x104000730
+// (lldb) memory read --format address --count 1 0x104000730
// 0x104000730: 0x0000000100002460 (void *)0x0000000100002488: MyString
-//
+//
// We can see that the first block is a "MyString" object that contains our
// pointer value at offset 16.
//
@@ -53,9 +55,9 @@
// (lldb) memory read -fA 0x100820000 -c1
// 0x100820000: 0x4f545541a1a1a1a1
// (lldb) memory read 0x100820000
-// 0x100820000: a1 a1 a1 a1 41 55 54 4f 52 45 4c 45 41 53 45 21 ....AUTORELEASE!
-// 0x100820010: 78 00 82 00 01 00 00 00 60 f9 e8 75 ff 7f 00 00 x.......`..u....
-//
+// 0x100820000: a1 a1 a1 a1 41 55 54 4f 52 45 4c 45 41 53 45 21 ....AUTORELEASE!
+// 0x100820010: 78 00 82 00 01 00 00 00 60 f9 e8 75 ff 7f 00 00 x.......`..u....
+//
// This is an objective C auto release pool object that contains our pointer.
// C++ classes will show up if they are virtual as something like:
// (lldb) memory read --format address --count 1 0x104008000
@@ -82,66 +84,47 @@
// Redefine private types from "/usr/local/include/stack_logging.h"
//----------------------------------------------------------------------
typedef struct {
- uint32_t type_flags;
- uint64_t stack_identifier;
- uint64_t argument;
- mach_vm_address_t address;
+ uint32_t type_flags;
+ uint64_t stack_identifier;
+ uint64_t argument;
+ mach_vm_address_t address;
} mach_stack_logging_record_t;
//----------------------------------------------------------------------
// Redefine private defines from "/usr/local/include/stack_logging.h"
//----------------------------------------------------------------------
-#define stack_logging_type_free 0
-#define stack_logging_type_generic 1
-#define stack_logging_type_alloc 2
-#define stack_logging_type_dealloc 4
+#define stack_logging_type_free 0
+#define stack_logging_type_generic 1
+#define stack_logging_type_alloc 2
+#define stack_logging_type_dealloc 4
// This bit is made up by this code
-#define stack_logging_type_vm_region 8
+#define stack_logging_type_vm_region 8
//----------------------------------------------------------------------
-// Redefine private function prototypes from
+// Redefine private function prototypes from
// "/usr/local/include/stack_logging.h"
//----------------------------------------------------------------------
-extern "C" kern_return_t
-__mach_stack_logging_set_file_path (
- task_t task,
- char* file_path
-);
-
-extern "C" kern_return_t
-__mach_stack_logging_get_frames (
- task_t task,
- mach_vm_address_t address,
- mach_vm_address_t *stack_frames_buffer,
- uint32_t max_stack_frames,
- uint32_t *count
-);
+extern "C" kern_return_t __mach_stack_logging_set_file_path(task_t task,
+ char *file_path);
extern "C" kern_return_t
-__mach_stack_logging_enumerate_records (
- task_t task,
- mach_vm_address_t address,
- void enumerator(mach_stack_logging_record_t, void *),
- void *context
-);
+__mach_stack_logging_get_frames(task_t task, mach_vm_address_t address,
+ mach_vm_address_t *stack_frames_buffer,
+ uint32_t max_stack_frames, uint32_t *count);
-extern "C" kern_return_t
-__mach_stack_logging_frames_for_uniqued_stack (
- task_t task,
- uint64_t stack_identifier,
- mach_vm_address_t *stack_frames_buffer,
- uint32_t max_stack_frames,
- uint32_t *count
-);
+extern "C" kern_return_t __mach_stack_logging_enumerate_records(
+ task_t task, mach_vm_address_t address,
+ void enumerator(mach_stack_logging_record_t, void *), void *context);
-extern "C" void *gdb_class_getClass (void *objc_class);
+extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack(
+ task_t task, uint64_t stack_identifier,
+ mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames,
+ uint32_t *count);
-static void
-range_info_callback (task_t task,
- void *baton,
- unsigned type,
- uint64_t ptr_addr,
- uint64_t ptr_size);
+extern "C" void *gdb_class_getClass(void *objc_class);
+
+static void range_info_callback(task_t task, void *baton, unsigned type,
+ uint64_t ptr_addr, uint64_t ptr_size);
//----------------------------------------------------------------------
// Redefine private global variables prototypes from
@@ -158,289 +141,221 @@ extern "C" int stack_logging_enable_logging;
//----------------------------------------------------------------------
// Local Typedefs and Types
//----------------------------------------------------------------------
-typedef void range_callback_t (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size);
-typedef void zone_callback_t (void *info, const malloc_zone_t *zone);
+typedef void range_callback_t(task_t task, void *baton, unsigned type,
+ uint64_t ptr_addr, uint64_t ptr_size);
+typedef void zone_callback_t(void *info, const malloc_zone_t *zone);
typedef int (*comare_function_t)(const void *, const void *);
-struct range_callback_info_t
-{
- zone_callback_t *zone_callback;
- range_callback_t *range_callback;
- void *baton;
- int check_vm_regions;
+struct range_callback_info_t {
+ zone_callback_t *zone_callback;
+ range_callback_t *range_callback;
+ void *baton;
+ int check_vm_regions;
};
-enum data_type_t
-{
- eDataTypeAddress,
- eDataTypeContainsData,
- eDataTypeObjC,
- eDataTypeHeapInfo
+enum data_type_t {
+ eDataTypeAddress,
+ eDataTypeContainsData,
+ eDataTypeObjC,
+ eDataTypeHeapInfo
};
-struct aligned_data_t
-{
- const uint8_t *buffer;
- uint32_t size;
- uint32_t align;
+struct aligned_data_t {
+ const uint8_t *buffer;
+ uint32_t size;
+ uint32_t align;
};
-struct objc_data_t
-{
- void *match_isa; // Set to NULL for all objective C objects
- bool match_superclasses;
+struct objc_data_t {
+ void *match_isa; // Set to NULL for all objective C objects
+ bool match_superclasses;
};
-struct range_contains_data_callback_info_t
-{
- data_type_t type;
- const void *lookup_addr;
- union
- {
- uintptr_t addr;
- aligned_data_t data;
- objc_data_t objc;
- };
- uint32_t match_count;
- bool done;
- bool unique;
+struct range_contains_data_callback_info_t {
+ data_type_t type;
+ const void *lookup_addr;
+ union {
+ uintptr_t addr;
+ aligned_data_t data;
+ objc_data_t objc;
+ };
+ uint32_t match_count;
+ bool done;
+ bool unique;
};
-struct malloc_match
-{
- void *addr;
- intptr_t size;
- intptr_t offset;
- uintptr_t type;
+struct malloc_match {
+ void *addr;
+ intptr_t size;
+ intptr_t offset;
+ uintptr_t type;
};
-struct malloc_stack_entry
-{
- const void *address;
- uint64_t argument;
- uint32_t type_flags;
- uint32_t num_frames;
- mach_vm_address_t frames[MAX_FRAMES];
+struct malloc_stack_entry {
+ const void *address;
+ uint64_t argument;
+ uint32_t type_flags;
+ uint32_t num_frames;
+ mach_vm_address_t frames[MAX_FRAMES];
};
-struct malloc_block_contents
-{
- union {
- Class isa;
- void *pointers[2];
- };
+struct malloc_block_contents {
+ union {
+ Class isa;
+ void *pointers[2];
+ };
};
-static int
-compare_void_ptr (const void *a, const void *b)
-{
- Class a_ptr = *(Class *)a;
- Class b_ptr = *(Class *)b;
- if (a_ptr < b_ptr) return -1;
- if (a_ptr > b_ptr) return +1;
- return 0;
+static int compare_void_ptr(const void *a, const void *b) {
+ Class a_ptr = *(Class *)a;
+ Class b_ptr = *(Class *)b;
+ if (a_ptr < b_ptr)
+ return -1;
+ if (a_ptr > b_ptr)
+ return +1;
+ return 0;
}
-class MatchResults
-{
- enum {
- k_max_entries = 8 * 1024
- };
-public:
- MatchResults () :
- m_size(0)
- {
- }
-
- void
- clear()
- {
- m_size = 0;
- bzero (&m_entries, sizeof(m_entries));
- }
-
- bool
- empty() const
- {
- return m_size == 0;
- }
-
- void
- push_back (const malloc_match& m, bool unique = false)
- {
- if (unique)
- {
- // Don't add the entry if there is already a match for this address
- for (uint32_t i=0; i<m_size; ++i)
- {
- if (((uint8_t *)m_entries[i].addr + m_entries[i].offset) == ((uint8_t *)m.addr + m.offset))
- return; // Duplicate entry
- }
- }
- if (m_size < k_max_entries - 1)
- {
- m_entries[m_size] = m;
- m_size++;
- }
- }
+class MatchResults {
+ enum { k_max_entries = 8 * 1024 };
- malloc_match *
- data ()
- {
- // If empty, return NULL
- if (empty())
- return NULL;
- // In not empty, terminate and return the result
- malloc_match terminator_entry = { NULL, 0, 0, 0 };
- // We always leave room for an empty entry at the end
- m_entries[m_size] = terminator_entry;
- return m_entries;
- }
+public:
+ MatchResults() : m_size(0) {}
+
+ void clear() {
+ m_size = 0;
+ bzero(&m_entries, sizeof(m_entries));
+ }
+
+ bool empty() const { return m_size == 0; }
+
+ void push_back(const malloc_match &m, bool unique = false) {
+ if (unique) {
+ // Don't add the entry if there is already a match for this address
+ for (uint32_t i = 0; i < m_size; ++i) {
+ if (((uint8_t *)m_entries[i].addr + m_entries[i].offset) ==
+ ((uint8_t *)m.addr + m.offset))
+ return; // Duplicate entry
+ }
+ }
+ if (m_size < k_max_entries - 1) {
+ m_entries[m_size] = m;
+ m_size++;
+ }
+ }
+
+ malloc_match *data() {
+ // If empty, return NULL
+ if (empty())
+ return NULL;
+ // In not empty, terminate and return the result
+ malloc_match terminator_entry = {NULL, 0, 0, 0};
+ // We always leave room for an empty entry at the end
+ m_entries[m_size] = terminator_entry;
+ return m_entries;
+ }
protected:
- malloc_match m_entries[k_max_entries];
- uint32_t m_size;
+ malloc_match m_entries[k_max_entries];
+ uint32_t m_size;
};
-class MallocStackLoggingEntries
-{
- enum { k_max_entries = 128 };
-public:
- MallocStackLoggingEntries () :
- m_size(0)
- {
- }
+class MallocStackLoggingEntries {
+ enum { k_max_entries = 128 };
- void
- clear()
- {
- m_size = 0;
- }
+public:
+ MallocStackLoggingEntries() : m_size(0) {}
- bool
- empty() const
- {
- return m_size == 0;
- }
+ void clear() { m_size = 0; }
+ bool empty() const { return m_size == 0; }
- malloc_stack_entry *
- next ()
- {
- if (m_size < k_max_entries - 1)
- {
- malloc_stack_entry * result = m_entries + m_size;
- ++m_size;
- return result;
- }
- return NULL; // Out of entries...
+ malloc_stack_entry *next() {
+ if (m_size < k_max_entries - 1) {
+ malloc_stack_entry *result = m_entries + m_size;
+ ++m_size;
+ return result;
}
+ return NULL; // Out of entries...
+ }
- malloc_stack_entry *
- data ()
- {
- // If empty, return NULL
- if (empty())
- return NULL;
- // In not empty, terminate and return the result
- m_entries[m_size].address = NULL;
- m_entries[m_size].argument = 0;
- m_entries[m_size].type_flags = 0;
- m_entries[m_size].num_frames = 0;
- return m_entries;
- }
+ malloc_stack_entry *data() {
+ // If empty, return NULL
+ if (empty())
+ return NULL;
+ // In not empty, terminate and return the result
+ m_entries[m_size].address = NULL;
+ m_entries[m_size].argument = 0;
+ m_entries[m_size].type_flags = 0;
+ m_entries[m_size].num_frames = 0;
+ return m_entries;
+ }
-protected:
- malloc_stack_entry m_entries[k_max_entries];
- uint32_t m_size;
+protected:
+ malloc_stack_entry m_entries[k_max_entries];
+ uint32_t m_size;
};
//----------------------------------------------------------------------
// A safe way to allocate memory and keep it from interfering with the
// malloc enumerators.
//----------------------------------------------------------------------
-void *
-safe_malloc(size_t n_bytes)
-{
- if (n_bytes > 0)
- {
- const int k_page_size = getpagesize();
- const mach_vm_size_t vm_size = ((n_bytes + k_page_size - 1)/k_page_size) * k_page_size;
- vm_address_t address = 0;
- kern_return_t kerr = vm_allocate (mach_task_self(), &address, vm_size, true);
- if (kerr == KERN_SUCCESS)
- return (void *)address;
- }
- return NULL;
+void *safe_malloc(size_t n_bytes) {
+ if (n_bytes > 0) {
+ const int k_page_size = getpagesize();
+ const mach_vm_size_t vm_size =
+ ((n_bytes + k_page_size - 1) / k_page_size) * k_page_size;
+ vm_address_t address = 0;
+ kern_return_t kerr = vm_allocate(mach_task_self(), &address, vm_size, true);
+ if (kerr == KERN_SUCCESS)
+ return (void *)address;
+ }
+ return NULL;
}
-
//----------------------------------------------------------------------
// ObjCClasses
//----------------------------------------------------------------------
-class ObjCClasses
-{
+class ObjCClasses {
public:
- ObjCClasses() :
- m_objc_class_ptrs (NULL),
- m_size (0)
- {
+ ObjCClasses() : m_objc_class_ptrs(NULL), m_size(0) {}
+
+ bool Update() {
+ // TODO: find out if class list has changed and update if needed
+ if (m_objc_class_ptrs == NULL) {
+ m_size = objc_getClassList(NULL, 0);
+ if (m_size > 0) {
+ // Allocate the class pointers
+ m_objc_class_ptrs = (Class *)safe_malloc(m_size * sizeof(Class));
+ m_size = objc_getClassList(m_objc_class_ptrs, m_size);
+ // Sort Class pointers for quick lookup
+ ::qsort(m_objc_class_ptrs, m_size, sizeof(Class), compare_void_ptr);
+ } else
+ return false;
}
+ return true;
+ }
- bool
- Update()
- {
- // TODO: find out if class list has changed and update if needed
- if (m_objc_class_ptrs == NULL)
- {
- m_size = objc_getClassList(NULL, 0);
- if (m_size > 0)
- {
- // Allocate the class pointers
- m_objc_class_ptrs = (Class *)safe_malloc (m_size * sizeof(Class));
- m_size = objc_getClassList(m_objc_class_ptrs, m_size);
- // Sort Class pointers for quick lookup
- ::qsort (m_objc_class_ptrs, m_size, sizeof(Class), compare_void_ptr);
- }
- else
- return false;
- }
- return true;
- }
-
- uint32_t
- FindClassIndex (Class isa)
- {
- Class *matching_class = (Class *)bsearch (&isa,
- m_objc_class_ptrs,
- m_size,
- sizeof(Class),
- compare_void_ptr);
- if (matching_class)
- {
- uint32_t idx = matching_class - m_objc_class_ptrs;
- return idx;
- }
- return UINT32_MAX;
- }
-
- Class
- GetClassAtIndex (uint32_t idx) const
- {
- if (idx < m_size)
- return m_objc_class_ptrs[idx];
- return NULL;
- }
- uint32_t
- GetSize() const
- {
- return m_size;
+ uint32_t FindClassIndex(Class isa) {
+ Class *matching_class = (Class *)bsearch(&isa, m_objc_class_ptrs, m_size,
+ sizeof(Class), compare_void_ptr);
+ if (matching_class) {
+ uint32_t idx = matching_class - m_objc_class_ptrs;
+ return idx;
}
-private:
- Class *m_objc_class_ptrs;
- uint32_t m_size;
-};
+ return UINT32_MAX;
+ }
+ Class GetClassAtIndex(uint32_t idx) const {
+ if (idx < m_size)
+ return m_objc_class_ptrs[idx];
+ return NULL;
+ }
+ uint32_t GetSize() const { return m_size; }
+private:
+ Class *m_objc_class_ptrs;
+ uint32_t m_size;
+};
//----------------------------------------------------------------------
// Local global variables
@@ -453,127 +368,104 @@ ObjCClasses g_objc_classes;
// ObjCClassInfo
//----------------------------------------------------------------------
-enum HeapInfoSortType
-{
- eSortTypeNone,
- eSortTypeBytes,
- eSortTypeCount
-};
+enum HeapInfoSortType { eSortTypeNone, eSortTypeBytes, eSortTypeCount };
-class ObjCClassInfo
-{
+class ObjCClassInfo {
public:
- ObjCClassInfo() :
- m_entries (NULL),
- m_size (0),
- m_sort_type (eSortTypeNone)
- {
- }
-
- void
- Update (const ObjCClasses &objc_classes)
- {
- m_size = objc_classes.GetSize();
- m_entries = (Entry *)safe_malloc (m_size * sizeof(Entry));
- m_sort_type = eSortTypeNone;
- Reset ();
- }
-
- bool
- AddInstance (uint32_t idx, uint64_t ptr_size)
- {
- if (m_size == 0)
- Update (g_objc_classes);
- // Update the totals for the classes
- if (idx < m_size)
- {
- m_entries[idx].bytes += ptr_size;
- ++m_entries[idx].count;
- return true;
- }
- return false;
- }
-
- void
- Reset ()
- {
- m_sort_type = eSortTypeNone;
- for (uint32_t i=0; i<m_size; ++i)
- {
- // In case we sort the entries after gathering the data, we will
- // want to know the index into the m_objc_class_ptrs[] array.
- m_entries[i].idx = i;
- m_entries[i].bytes = 0;
- m_entries[i].count = 0;
- }
- }
- void
- SortByTotalBytes (const ObjCClasses &objc_classes, bool print)
- {
- if (m_sort_type != eSortTypeBytes && m_size > 0)
- {
- ::qsort (m_entries, m_size, sizeof(Entry), (comare_function_t)compare_bytes);
- m_sort_type = eSortTypeBytes;
- }
- if (print && m_size > 0)
- {
- puts("Objective C objects by total bytes:");
- puts("Total Bytes Class Name");
- puts("----------- -----------------------------------------------------------------");
- for (uint32_t i=0; i<m_size && m_entries[i].bytes > 0; ++i)
- {
- printf ("%11llu %s\n", m_entries[i].bytes, class_getName (objc_classes.GetClassAtIndex(m_entries[i].idx)));
- }
- }
- }
- void
- SortByTotalCount (const ObjCClasses &objc_classes, bool print)
- {
- if (m_sort_type != eSortTypeCount && m_size > 0)
- {
- ::qsort (m_entries, m_size, sizeof(Entry), (comare_function_t)compare_count);
- m_sort_type = eSortTypeCount;
- }
- if (print && m_size > 0)
- {
- puts("Objective C objects by total count:");
- puts("Count Class Name");
- puts("-------- -----------------------------------------------------------------");
- for (uint32_t i=0; i<m_size && m_entries[i].count > 0; ++i)
- {
- printf ("%8u %s\n", m_entries[i].count, class_getName (objc_classes.GetClassAtIndex(m_entries[i].idx)));
- }
- }
- }
-private:
- struct Entry
- {
- uint32_t idx; // Index into the m_objc_class_ptrs[] array
- uint32_t count; // Number of object instances that were found
- uint64_t bytes; // Total number of bytes for each objc class
- };
-
- static int
- compare_bytes (const Entry *a, const Entry *b)
- {
- // Reverse the comparison to most bytes entries end up at top of list
- if (a->bytes > b->bytes) return -1;
- if (a->bytes < b->bytes) return +1;
- return 0;
- }
+ ObjCClassInfo() : m_entries(NULL), m_size(0), m_sort_type(eSortTypeNone) {}
+
+ void Update(const ObjCClasses &objc_classes) {
+ m_size = objc_classes.GetSize();
+ m_entries = (Entry *)safe_malloc(m_size * sizeof(Entry));
+ m_sort_type = eSortTypeNone;
+ Reset();
+ }
+
+ bool AddInstance(uint32_t idx, uint64_t ptr_size) {
+ if (m_size == 0)
+ Update(g_objc_classes);
+ // Update the totals for the classes
+ if (idx < m_size) {
+ m_entries[idx].bytes += ptr_size;
+ ++m_entries[idx].count;
+ return true;
+ }
+ return false;
+ }
+
+ void Reset() {
+ m_sort_type = eSortTypeNone;
+ for (uint32_t i = 0; i < m_size; ++i) {
+ // In case we sort the entries after gathering the data, we will
+ // want to know the index into the m_objc_class_ptrs[] array.
+ m_entries[i].idx = i;
+ m_entries[i].bytes = 0;
+ m_entries[i].count = 0;
+ }
+ }
+ void SortByTotalBytes(const ObjCClasses &objc_classes, bool print) {
+ if (m_sort_type != eSortTypeBytes && m_size > 0) {
+ ::qsort(m_entries, m_size, sizeof(Entry),
+ (comare_function_t)compare_bytes);
+ m_sort_type = eSortTypeBytes;
+ }
+ if (print && m_size > 0) {
+ puts("Objective C objects by total bytes:");
+ puts("Total Bytes Class Name");
+ puts("----------- "
+ "-----------------------------------------------------------------");
+ for (uint32_t i = 0; i < m_size && m_entries[i].bytes > 0; ++i) {
+ printf("%11llu %s\n", m_entries[i].bytes,
+ class_getName(objc_classes.GetClassAtIndex(m_entries[i].idx)));
+ }
+ }
+ }
+ void SortByTotalCount(const ObjCClasses &objc_classes, bool print) {
+ if (m_sort_type != eSortTypeCount && m_size > 0) {
+ ::qsort(m_entries, m_size, sizeof(Entry),
+ (comare_function_t)compare_count);
+ m_sort_type = eSortTypeCount;
+ }
+ if (print && m_size > 0) {
+ puts("Objective C objects by total count:");
+ puts("Count Class Name");
+ puts("-------- "
+ "-----------------------------------------------------------------");
+ for (uint32_t i = 0; i < m_size && m_entries[i].count > 0; ++i) {
+ printf("%8u %s\n", m_entries[i].count,
+ class_getName(objc_classes.GetClassAtIndex(m_entries[i].idx)));
+ }
+ }
+ }
- static int
- compare_count (const Entry *a, const Entry *b)
- {
- // Reverse the comparison to most count entries end up at top of list
- if (a->count > b->count) return -1;
- if (a->count < b->count) return +1;
- return 0;
- }
+private:
+ struct Entry {
+ uint32_t idx; // Index into the m_objc_class_ptrs[] array
+ uint32_t count; // Number of object instances that were found
+ uint64_t bytes; // Total number of bytes for each objc class
+ };
+
+ static int compare_bytes(const Entry *a, const Entry *b) {
+ // Reverse the comparison to most bytes entries end up at top of list
+ if (a->bytes > b->bytes)
+ return -1;
+ if (a->bytes < b->bytes)
+ return +1;
+ return 0;
+ }
+
+ static int compare_count(const Entry *a, const Entry *b) {
+ // Reverse the comparison to most count entries end up at top of list
+ if (a->count > b->count)
+ return -1;
+ if (a->count < b->count)
+ return +1;
+ return 0;
+ }
- Entry *m_entries;
- uint32_t m_size;
- HeapInfoSortType m_sort_type;
+ Entry *m_entries;
+ uint32_t m_size;
+ HeapInfoSortType m_sort_type;
};
ObjCClassInfo g_objc_class_snapshot;
@@ -585,74 +477,62 @@ ObjCClassInfo g_objc_class_snapshot;
// by the code that iterates through all of the malloc blocks to read
// the memory in this process.
//----------------------------------------------------------------------
-static kern_return_t
-task_peek (task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory)
-{
- *local_memory = (void*) remote_address;
- return KERN_SUCCESS;
+static kern_return_t task_peek(task_t task, vm_address_t remote_address,
+ vm_size_t size, void **local_memory) {
+ *local_memory = (void *)remote_address;
+ return KERN_SUCCESS;
}
+static const void foreach_zone_in_this_process(range_callback_info_t *info) {
+ if (info == NULL || info->zone_callback == NULL)
+ return;
-static const void
-foreach_zone_in_this_process (range_callback_info_t *info)
-{
- if (info == NULL || info->zone_callback == NULL)
- return;
+ vm_address_t *zones = NULL;
+ unsigned int num_zones = 0;
- vm_address_t *zones = NULL;
- unsigned int num_zones = 0;
-
- kern_return_t err = malloc_get_all_zones (0, task_peek, &zones, &num_zones);
- if (KERN_SUCCESS == err)
- {
- for (unsigned int i=0; i<num_zones; ++i)
- {
- info->zone_callback (info, (const malloc_zone_t *)zones[i]);
- }
+ kern_return_t err = malloc_get_all_zones(0, task_peek, &zones, &num_zones);
+ if (KERN_SUCCESS == err) {
+ for (unsigned int i = 0; i < num_zones; ++i) {
+ info->zone_callback(info, (const malloc_zone_t *)zones[i]);
}
-
- if (info->check_vm_regions)
- {
-#if defined (VM_REGION_SUBMAP_SHORT_INFO_COUNT_64)
- typedef vm_region_submap_short_info_data_64_t RegionInfo;
- enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
+ }
+
+ if (info->check_vm_regions) {
+#if defined(VM_REGION_SUBMAP_SHORT_INFO_COUNT_64)
+ typedef vm_region_submap_short_info_data_64_t RegionInfo;
+ enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
#else
- typedef vm_region_submap_info_data_64_t RegionInfo;
- enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 };
+ typedef vm_region_submap_info_data_64_t RegionInfo;
+ enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 };
#endif
- task_t task = mach_task_self();
- mach_vm_address_t vm_region_base_addr;
- mach_vm_size_t vm_region_size;
- natural_t vm_region_depth;
- RegionInfo vm_region_info;
-
- ((range_contains_data_callback_info_t *)info->baton)->unique = true;
-
- for (vm_region_base_addr = 0, vm_region_size = 1; vm_region_size != 0; vm_region_base_addr += vm_region_size)
- {
- mach_msg_type_number_t vm_region_info_size = kRegionInfoSize;
- const kern_return_t err = mach_vm_region_recurse (task,
- &vm_region_base_addr,
- &vm_region_size,
- &vm_region_depth,
- (vm_region_recurse_info_t)&vm_region_info,
- &vm_region_info_size);
- if (err)
- break;
- // Check all read + write regions. This will cover the thread stacks
- // and any regions of memory that aren't covered by the heap
- if (vm_region_info.protection & VM_PROT_WRITE &&
- vm_region_info.protection & VM_PROT_READ)
- {
- //printf ("checking vm_region: [0x%16.16llx - 0x%16.16llx)\n", (uint64_t)vm_region_base_addr, (uint64_t)vm_region_base_addr + vm_region_size);
- range_info_callback (task,
- info->baton,
- stack_logging_type_vm_region,
- vm_region_base_addr,
- vm_region_size);
- }
- }
- }
+ task_t task = mach_task_self();
+ mach_vm_address_t vm_region_base_addr;
+ mach_vm_size_t vm_region_size;
+ natural_t vm_region_depth;
+ RegionInfo vm_region_info;
+
+ ((range_contains_data_callback_info_t *)info->baton)->unique = true;
+
+ for (vm_region_base_addr = 0, vm_region_size = 1; vm_region_size != 0;
+ vm_region_base_addr += vm_region_size) {
+ mach_msg_type_number_t vm_region_info_size = kRegionInfoSize;
+ const kern_return_t err = mach_vm_region_recurse(
+ task, &vm_region_base_addr, &vm_region_size, &vm_region_depth,
+ (vm_region_recurse_info_t)&vm_region_info, &vm_region_info_size);
+ if (err)
+ break;
+ // Check all read + write regions. This will cover the thread stacks
+ // and any regions of memory that aren't covered by the heap
+ if (vm_region_info.protection & VM_PROT_WRITE &&
+ vm_region_info.protection & VM_PROT_READ) {
+ // printf ("checking vm_region: [0x%16.16llx - 0x%16.16llx)\n",
+ // (uint64_t)vm_region_base_addr, (uint64_t)vm_region_base_addr +
+ // vm_region_size);
+ range_info_callback(task, info->baton, stack_logging_type_vm_region,
+ vm_region_base_addr, vm_region_size);
+ }
+ }
+ }
}
//----------------------------------------------------------------------
@@ -661,235 +541,203 @@ foreach_zone_in_this_process (range_callback_info_t *info)
// A simple callback that will dump each malloc block and all available
// info from the enumeration callback perspective.
//----------------------------------------------------------------------
-static void
-dump_malloc_block_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
-{
- printf ("task = 0x%4.4x: baton = %p, type = %u, ptr_addr = 0x%llx + 0x%llu\n", task, baton, type, ptr_addr, ptr_size);
+static void dump_malloc_block_callback(task_t task, void *baton, unsigned type,
+ uint64_t ptr_addr, uint64_t ptr_size) {
+ printf("task = 0x%4.4x: baton = %p, type = %u, ptr_addr = 0x%llx + 0x%llu\n",
+ task, baton, type, ptr_addr, ptr_size);
}
-static void
-ranges_callback (task_t task, void *baton, unsigned type, vm_range_t *ptrs, unsigned count)
-{
- range_callback_info_t *info = (range_callback_info_t *)baton;
- while(count--) {
- info->range_callback (task, info->baton, type, ptrs->address, ptrs->size);
- ptrs++;
- }
+static void ranges_callback(task_t task, void *baton, unsigned type,
+ vm_range_t *ptrs, unsigned count) {
+ range_callback_info_t *info = (range_callback_info_t *)baton;
+ while (count--) {
+ info->range_callback(task, info->baton, type, ptrs->address, ptrs->size);
+ ptrs++;
+ }
}
-static void
-enumerate_range_in_zone (void *baton, const malloc_zone_t *zone)
-{
- range_callback_info_t *info = (range_callback_info_t *)baton;
-
- if (zone && zone->introspect)
- zone->introspect->enumerator (mach_task_self(),
- info,
- MALLOC_PTR_IN_USE_RANGE_TYPE,
- (vm_address_t)zone,
- task_peek,
- ranges_callback);
+static void enumerate_range_in_zone(void *baton, const malloc_zone_t *zone) {
+ range_callback_info_t *info = (range_callback_info_t *)baton;
+
+ if (zone && zone->introspect)
+ zone->introspect->enumerator(
+ mach_task_self(), info, MALLOC_PTR_IN_USE_RANGE_TYPE,
+ (vm_address_t)zone, task_peek, ranges_callback);
}
-static void
-range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
-{
- const uint64_t end_addr = ptr_addr + ptr_size;
-
- range_contains_data_callback_info_t *info = (range_contains_data_callback_info_t *)baton;
- switch (info->type)
- {
- case eDataTypeAddress:
- // Check if the current malloc block contains an address specified by "info->addr"
- if (ptr_addr <= info->addr && info->addr < end_addr)
- {
- ++info->match_count;
- malloc_match match = { (void *)ptr_addr, ptr_size, info->addr - ptr_addr, type };
- g_matches.push_back(match, info->unique);
- }
- break;
-
- case eDataTypeContainsData:
- // Check if the current malloc block contains data specified in "info->data"
- {
- const uint32_t size = info->data.size;
- if (size < ptr_size) // Make sure this block can contain this data
- {
- uint8_t *ptr_data = NULL;
- if (task_peek (task, ptr_addr, ptr_size, (void **)&ptr_data) == KERN_SUCCESS)
- {
- const void *buffer = info->data.buffer;
- assert (ptr_data);
- const uint32_t align = info->data.align;
- for (uint64_t addr = ptr_addr;
- addr < end_addr && ((end_addr - addr) >= size);
- addr += align, ptr_data += align)
- {
- if (memcmp (buffer, ptr_data, size) == 0)
- {
- ++info->match_count;
- malloc_match match = { (void *)ptr_addr, ptr_size, addr - ptr_addr, type };
- g_matches.push_back(match, info->unique);
- }
- }
- }
- else
- {
- printf ("0x%llx: error: couldn't read %llu bytes\n", ptr_addr, ptr_size);
- }
+static void range_info_callback(task_t task, void *baton, unsigned type,
+ uint64_t ptr_addr, uint64_t ptr_size) {
+ const uint64_t end_addr = ptr_addr + ptr_size;
+
+ range_contains_data_callback_info_t *info =
+ (range_contains_data_callback_info_t *)baton;
+ switch (info->type) {
+ case eDataTypeAddress:
+ // Check if the current malloc block contains an address specified by
+ // "info->addr"
+ if (ptr_addr <= info->addr && info->addr < end_addr) {
+ ++info->match_count;
+ malloc_match match = {(void *)ptr_addr, ptr_size, info->addr - ptr_addr,
+ type};
+ g_matches.push_back(match, info->unique);
+ }
+ break;
+
+ case eDataTypeContainsData:
+ // Check if the current malloc block contains data specified in "info->data"
+ {
+ const uint32_t size = info->data.size;
+ if (size < ptr_size) // Make sure this block can contain this data
+ {
+ uint8_t *ptr_data = NULL;
+ if (task_peek(task, ptr_addr, ptr_size, (void **)&ptr_data) ==
+ KERN_SUCCESS) {
+ const void *buffer = info->data.buffer;
+ assert(ptr_data);
+ const uint32_t align = info->data.align;
+ for (uint64_t addr = ptr_addr;
+ addr < end_addr && ((end_addr - addr) >= size);
+ addr += align, ptr_data += align) {
+ if (memcmp(buffer, ptr_data, size) == 0) {
+ ++info->match_count;
+ malloc_match match = {(void *)ptr_addr, ptr_size, addr - ptr_addr,
+ type};
+ g_matches.push_back(match, info->unique);
}
+ }
+ } else {
+ printf("0x%llx: error: couldn't read %llu bytes\n", ptr_addr,
+ ptr_size);
}
- break;
-
- case eDataTypeObjC:
- // Check if the current malloc block contains an objective C object
- // of any sort where the first pointer in the object is an OBJC class
- // pointer (an isa)
- {
- malloc_block_contents *block_contents = NULL;
- if (task_peek (task, ptr_addr, sizeof(void *), (void **)&block_contents) == KERN_SUCCESS)
- {
- // We assume that g_objc_classes is up to date
- // that the class list was verified to have some classes in it
- // before calling this function
- const uint32_t objc_class_idx = g_objc_classes.FindClassIndex (block_contents->isa);
- if (objc_class_idx != UINT32_MAX)
- {
- bool match = false;
- if (info->objc.match_isa == 0)
- {
- // Match any objective C object
- match = true;
- }
- else
- {
- // Only match exact isa values in the current class or
- // optionally in the super classes
- if (info->objc.match_isa == block_contents->isa)
- match = true;
- else if (info->objc.match_superclasses)
- {
- Class super = class_getSuperclass(block_contents->isa);
- while (super)
- {
- match = super == info->objc.match_isa;
- if (match)
- break;
- super = class_getSuperclass(super);
- }
- }
- }
- if (match)
- {
- //printf (" success\n");
- ++info->match_count;
- malloc_match match = { (void *)ptr_addr, ptr_size, 0, type };
- g_matches.push_back(match, info->unique);
- }
- else
- {
- //printf (" error: wrong class: %s\n", dl_info.dli_sname);
- }
- }
- else
- {
- //printf ("\terror: symbol not objc class: %s\n", dl_info.dli_sname);
- return;
- }
+ }
+ }
+ break;
+
+ case eDataTypeObjC:
+ // Check if the current malloc block contains an objective C object
+ // of any sort where the first pointer in the object is an OBJC class
+ // pointer (an isa)
+ {
+ malloc_block_contents *block_contents = NULL;
+ if (task_peek(task, ptr_addr, sizeof(void *), (void **)&block_contents) ==
+ KERN_SUCCESS) {
+ // We assume that g_objc_classes is up to date
+ // that the class list was verified to have some classes in it
+ // before calling this function
+ const uint32_t objc_class_idx =
+ g_objc_classes.FindClassIndex(block_contents->isa);
+ if (objc_class_idx != UINT32_MAX) {
+ bool match = false;
+ if (info->objc.match_isa == 0) {
+ // Match any objective C object
+ match = true;
+ } else {
+ // Only match exact isa values in the current class or
+ // optionally in the super classes
+ if (info->objc.match_isa == block_contents->isa)
+ match = true;
+ else if (info->objc.match_superclasses) {
+ Class super = class_getSuperclass(block_contents->isa);
+ while (super) {
+ match = super == info->objc.match_isa;
+ if (match)
+ break;
+ super = class_getSuperclass(super);
+ }
}
+ }
+ if (match) {
+ // printf (" success\n");
+ ++info->match_count;
+ malloc_match match = {(void *)ptr_addr, ptr_size, 0, type};
+ g_matches.push_back(match, info->unique);
+ } else {
+ // printf (" error: wrong class: %s\n", dl_info.dli_sname);
+ }
+ } else {
+ // printf ("\terror: symbol not objc class: %s\n", dl_info.dli_sname);
+ return;
}
- break;
-
- case eDataTypeHeapInfo:
- // Check if the current malloc block contains an objective C object
- // of any sort where the first pointer in the object is an OBJC class
- // pointer (an isa)
- {
- malloc_block_contents *block_contents = NULL;
- if (task_peek (task, ptr_addr, sizeof(void *), (void **)&block_contents) == KERN_SUCCESS)
- {
- // We assume that g_objc_classes is up to date
- // that the class list was verified to have some classes in it
- // before calling this function
- const uint32_t objc_class_idx = g_objc_classes.FindClassIndex (block_contents->isa);
- if (objc_class_idx != UINT32_MAX)
- {
- // This is an objective C object
- g_objc_class_snapshot.AddInstance (objc_class_idx, ptr_size);
- }
- else
- {
- // Classify other heap info
- }
- }
+ }
+ }
+ break;
+
+ case eDataTypeHeapInfo:
+ // Check if the current malloc block contains an objective C object
+ // of any sort where the first pointer in the object is an OBJC class
+ // pointer (an isa)
+ {
+ malloc_block_contents *block_contents = NULL;
+ if (task_peek(task, ptr_addr, sizeof(void *), (void **)&block_contents) ==
+ KERN_SUCCESS) {
+ // We assume that g_objc_classes is up to date
+ // that the class list was verified to have some classes in it
+ // before calling this function
+ const uint32_t objc_class_idx =
+ g_objc_classes.FindClassIndex(block_contents->isa);
+ if (objc_class_idx != UINT32_MAX) {
+ // This is an objective C object
+ g_objc_class_snapshot.AddInstance(objc_class_idx, ptr_size);
+ } else {
+ // Classify other heap info
}
- break;
-
+ }
}
+ break;
+ }
+}
+
+static void
+get_stack_for_address_enumerator(mach_stack_logging_record_t stack_record,
+ void *task_ptr) {
+ malloc_stack_entry *stack_entry = g_malloc_stack_history.next();
+ if (stack_entry) {
+ stack_entry->address = (void *)stack_record.address;
+ stack_entry->type_flags = stack_record.type_flags;
+ stack_entry->argument = stack_record.argument;
+ stack_entry->num_frames = 0;
+ stack_entry->frames[0] = 0;
+ kern_return_t err = __mach_stack_logging_frames_for_uniqued_stack(
+ *(task_t *)task_ptr, stack_record.stack_identifier, stack_entry->frames,
+ MAX_FRAMES, &stack_entry->num_frames);
+ // Terminate the frames with zero if there is room
+ if (stack_entry->num_frames < MAX_FRAMES)
+ stack_entry->frames[stack_entry->num_frames] = 0;
+ }
}
-static void
-get_stack_for_address_enumerator(mach_stack_logging_record_t stack_record, void *task_ptr)
-{
+malloc_stack_entry *get_stack_history_for_address(const void *addr,
+ int history) {
+ if (!stack_logging_enable_logging)
+ return NULL;
+ g_malloc_stack_history.clear();
+ kern_return_t err;
+ task_t task = mach_task_self();
+ if (history) {
+ err = __mach_stack_logging_enumerate_records(
+ task, (mach_vm_address_t)addr, get_stack_for_address_enumerator, &task);
+ } else {
malloc_stack_entry *stack_entry = g_malloc_stack_history.next();
- if (stack_entry)
- {
- stack_entry->address = (void *)stack_record.address;
- stack_entry->type_flags = stack_record.type_flags;
- stack_entry->argument = stack_record.argument;
- stack_entry->num_frames = 0;
- stack_entry->frames[0] = 0;
- kern_return_t err = __mach_stack_logging_frames_for_uniqued_stack (*(task_t *)task_ptr,
- stack_record.stack_identifier,
- stack_entry->frames,
- MAX_FRAMES,
- &stack_entry->num_frames);
+ if (stack_entry) {
+ stack_entry->address = addr;
+ stack_entry->type_flags = stack_logging_type_alloc;
+ stack_entry->argument = 0;
+ stack_entry->num_frames = 0;
+ stack_entry->frames[0] = 0;
+ err = __mach_stack_logging_get_frames(task, (mach_vm_address_t)addr,
+ stack_entry->frames, MAX_FRAMES,
+ &stack_entry->num_frames);
+ if (err == 0 && stack_entry->num_frames > 0) {
// Terminate the frames with zero if there is room
if (stack_entry->num_frames < MAX_FRAMES)
- stack_entry->frames[stack_entry->num_frames] = 0;
- }
-}
-
-malloc_stack_entry *
-get_stack_history_for_address (const void * addr, int history)
-{
- if (!stack_logging_enable_logging)
- return NULL;
- g_malloc_stack_history.clear();
- kern_return_t err;
- task_t task = mach_task_self();
- if (history)
- {
- err = __mach_stack_logging_enumerate_records (task,
- (mach_vm_address_t)addr,
- get_stack_for_address_enumerator,
- &task);
- }
- else
- {
- malloc_stack_entry *stack_entry = g_malloc_stack_history.next();
- if (stack_entry)
- {
- stack_entry->address = addr;
- stack_entry->type_flags = stack_logging_type_alloc;
- stack_entry->argument = 0;
- stack_entry->num_frames = 0;
- stack_entry->frames[0] = 0;
- err = __mach_stack_logging_get_frames(task, (mach_vm_address_t)addr, stack_entry->frames, MAX_FRAMES, &stack_entry->num_frames);
- if (err == 0 && stack_entry->num_frames > 0)
- {
- // Terminate the frames with zero if there is room
- if (stack_entry->num_frames < MAX_FRAMES)
- stack_entry->frames[stack_entry->num_frames] = 0;
- }
- else
- {
- g_malloc_stack_history.clear();
- }
- }
- }
- // Return data if there is any
- return g_malloc_stack_history.data();
+ stack_entry->frames[stack_entry->num_frames] = 0;
+ } else {
+ g_malloc_stack_history.clear();
+ }
+ }
+ }
+ // Return data if there is any
+ return g_malloc_stack_history.data();
}
//----------------------------------------------------------------------
@@ -898,28 +746,26 @@ get_stack_history_for_address (const void * addr, int history)
// Finds a pointer value inside one or more currently valid malloc
// blocks.
//----------------------------------------------------------------------
-malloc_match *
-find_pointer_in_heap (const void * addr, int check_vm_regions)
-{
- g_matches.clear();
- // Setup "info" to look for a malloc block that contains data
- // that is the pointer
- if (addr)
- {
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeContainsData; // Check each block for data
- data_info.data.buffer = (uint8_t *)&addr; // What data? The pointer value passed in
- data_info.data.size = sizeof(addr); // How many bytes? The byte size of a pointer
- data_info.data.align = sizeof(addr); // Align to a pointer byte size
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info, check_vm_regions };
- foreach_zone_in_this_process (&info);
-
-
- }
- return g_matches.data();
+malloc_match *find_pointer_in_heap(const void *addr, int check_vm_regions) {
+ g_matches.clear();
+ // Setup "info" to look for a malloc block that contains data
+ // that is the pointer
+ if (addr) {
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeContainsData; // Check each block for data
+ data_info.data.buffer =
+ (uint8_t *)&addr; // What data? The pointer value passed in
+ data_info.data.size =
+ sizeof(addr); // How many bytes? The byte size of a pointer
+ data_info.data.align = sizeof(addr); // Align to a pointer byte size
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ range_callback_info_t info = {enumerate_range_in_zone, range_info_callback,
+ &data_info, check_vm_regions};
+ foreach_zone_in_this_process(&info);
+ }
+ return g_matches.data();
}
//----------------------------------------------------------------------
@@ -928,95 +774,90 @@ find_pointer_in_heap (const void * addr, int check_vm_regions)
// Finds a pointer value inside one or more currently valid malloc
// blocks.
//----------------------------------------------------------------------
-malloc_match *
-find_pointer_in_memory (uint64_t memory_addr, uint64_t memory_size, const void * addr)
-{
- g_matches.clear();
- // Setup "info" to look for a malloc block that contains data
- // that is the pointer
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeContainsData; // Check each block for data
- data_info.data.buffer = (uint8_t *)&addr; // What data? The pointer value passed in
- data_info.data.size = sizeof(addr); // How many bytes? The byte size of a pointer
- data_info.data.align = sizeof(addr); // Align to a pointer byte size
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- range_info_callback (mach_task_self(), &data_info, stack_logging_type_generic, memory_addr, memory_size);
- return g_matches.data();
+malloc_match *find_pointer_in_memory(uint64_t memory_addr, uint64_t memory_size,
+ const void *addr) {
+ g_matches.clear();
+ // Setup "info" to look for a malloc block that contains data
+ // that is the pointer
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeContainsData; // Check each block for data
+ data_info.data.buffer =
+ (uint8_t *)&addr; // What data? The pointer value passed in
+ data_info.data.size =
+ sizeof(addr); // How many bytes? The byte size of a pointer
+ data_info.data.align = sizeof(addr); // Align to a pointer byte size
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ range_info_callback(mach_task_self(), &data_info, stack_logging_type_generic,
+ memory_addr, memory_size);
+ return g_matches.data();
}
//----------------------------------------------------------------------
// find_objc_objects_in_memory
//
// Find all instances of ObjC classes 'c', or all ObjC classes if 'c' is
-// NULL. If 'c' is non NULL, then also check objects to see if they
+// NULL. If 'c' is non NULL, then also check objects to see if they
// inherit from 'c'
//----------------------------------------------------------------------
-malloc_match *
-find_objc_objects_in_memory (void *isa, int check_vm_regions)
-{
- g_matches.clear();
- if (g_objc_classes.Update())
- {
- // Setup "info" to look for a malloc block that contains data
- // that is the pointer
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeObjC; // Check each block for data
- data_info.objc.match_isa = isa;
- data_info.objc.match_superclasses = true;
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info, check_vm_regions };
- foreach_zone_in_this_process (&info);
- }
- return g_matches.data();
+malloc_match *find_objc_objects_in_memory(void *isa, int check_vm_regions) {
+ g_matches.clear();
+ if (g_objc_classes.Update()) {
+ // Setup "info" to look for a malloc block that contains data
+ // that is the pointer
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeObjC; // Check each block for data
+ data_info.objc.match_isa = isa;
+ data_info.objc.match_superclasses = true;
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ range_callback_info_t info = {enumerate_range_in_zone, range_info_callback,
+ &data_info, check_vm_regions};
+ foreach_zone_in_this_process(&info);
+ }
+ return g_matches.data();
}
//----------------------------------------------------------------------
// get_heap_info
//
-// Gather information for all allocations on the heap and report
+// Gather information for all allocations on the heap and report
// statistics.
//----------------------------------------------------------------------
-void
-get_heap_info (int sort_type)
-{
- if (g_objc_classes.Update())
- {
- // Reset all stats
- g_objc_class_snapshot.Reset ();
- // Setup "info" to look for a malloc block that contains data
- // that is the pointer
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeHeapInfo; // Check each block for data
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- const int check_vm_regions = false;
- range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info, check_vm_regions };
- foreach_zone_in_this_process (&info);
-
- // Sort and print byte total bytes
- switch (sort_type)
- {
- case eSortTypeNone:
- default:
- case eSortTypeBytes:
- g_objc_class_snapshot.SortByTotalBytes(g_objc_classes, true);
- break;
-
- case eSortTypeCount:
- g_objc_class_snapshot.SortByTotalCount(g_objc_classes, true);
- break;
- }
- }
- else
- {
- printf ("error: no objective C classes\n");
- }
+void get_heap_info(int sort_type) {
+ if (g_objc_classes.Update()) {
+ // Reset all stats
+ g_objc_class_snapshot.Reset();
+ // Setup "info" to look for a malloc block that contains data
+ // that is the pointer
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeHeapInfo; // Check each block for data
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ const int check_vm_regions = false;
+ range_callback_info_t info = {enumerate_range_in_zone, range_info_callback,
+ &data_info, check_vm_regions};
+ foreach_zone_in_this_process(&info);
+
+ // Sort and print byte total bytes
+ switch (sort_type) {
+ case eSortTypeNone:
+ default:
+ case eSortTypeBytes:
+ g_objc_class_snapshot.SortByTotalBytes(g_objc_classes, true);
+ break;
+
+ case eSortTypeCount:
+ g_objc_class_snapshot.SortByTotalCount(g_objc_classes, true);
+ break;
+ }
+ } else {
+ printf("error: no objective C classes\n");
+ }
}
//----------------------------------------------------------------------
@@ -1024,28 +865,27 @@ get_heap_info (int sort_type)
//
// Finds a C string inside one or more currently valid malloc blocks.
//----------------------------------------------------------------------
-malloc_match *
-find_cstring_in_heap (const char *s, int check_vm_regions)
-{
- g_matches.clear();
- if (s == NULL || s[0] == '\0')
- {
- printf ("error: invalid argument (empty cstring)\n");
- return NULL;
- }
- // Setup "info" to look for a malloc block that contains data
- // that is the C string passed in aligned on a 1 byte boundary
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeContainsData; // Check each block for data
- data_info.data.buffer = (uint8_t *)s; // What data? The C string passed in
- data_info.data.size = strlen(s); // How many bytes? The length of the C string
- data_info.data.align = 1; // Data doesn't need to be aligned, so set the alignment to 1
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info, check_vm_regions };
- foreach_zone_in_this_process (&info);
- return g_matches.data();
+malloc_match *find_cstring_in_heap(const char *s, int check_vm_regions) {
+ g_matches.clear();
+ if (s == NULL || s[0] == '\0') {
+ printf("error: invalid argument (empty cstring)\n");
+ return NULL;
+ }
+ // Setup "info" to look for a malloc block that contains data
+ // that is the C string passed in aligned on a 1 byte boundary
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeContainsData; // Check each block for data
+ data_info.data.buffer = (uint8_t *)s; // What data? The C string passed in
+ data_info.data.size = strlen(s); // How many bytes? The length of the C string
+ data_info.data.align =
+ 1; // Data doesn't need to be aligned, so set the alignment to 1
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ range_callback_info_t info = {enumerate_range_in_zone, range_info_callback,
+ &data_info, check_vm_regions};
+ foreach_zone_in_this_process(&info);
+ return g_matches.data();
}
//----------------------------------------------------------------------
@@ -1053,19 +893,19 @@ find_cstring_in_heap (const char *s, int check_vm_regions)
//
// Find the malloc block that whose address range contains "addr".
//----------------------------------------------------------------------
-malloc_match *
-find_block_for_address (const void *addr, int check_vm_regions)
-{
- g_matches.clear();
- // Setup "info" to look for a malloc block that contains data
- // that is the C string passed in aligned on a 1 byte boundary
- range_contains_data_callback_info_t data_info;
- data_info.type = eDataTypeAddress; // Check each block to see if the block contains the address passed in
- data_info.addr = (uintptr_t)addr; // What data? The C string passed in
- data_info.match_count = 0; // Initialize the match count to zero
- data_info.done = false; // Set done to false so searching doesn't stop
- data_info.unique = false; // Set to true when iterating on the vm_regions
- range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info, check_vm_regions };
- foreach_zone_in_this_process (&info);
- return g_matches.data();
+malloc_match *find_block_for_address(const void *addr, int check_vm_regions) {
+ g_matches.clear();
+ // Setup "info" to look for a malloc block that contains data
+ // that is the C string passed in aligned on a 1 byte boundary
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeAddress; // Check each block to see if the block
+ // contains the address passed in
+ data_info.addr = (uintptr_t)addr; // What data? The C string passed in
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ data_info.unique = false; // Set to true when iterating on the vm_regions
+ range_callback_info_t info = {enumerate_range_in_zone, range_info_callback,
+ &data_info, check_vm_regions};
+ foreach_zone_in_this_process(&info);
+ return g_matches.data();
}
OpenPOWER on IntegriCloud