[Lldb-commits] [lldb] r148523 - in /lldb/trunk/examples/darwin: ./ heap_find/ heap_find/Makefile heap_find/heap_find.c
Greg Clayton
gclayton at apple.com
Thu Jan 19 17:31:25 PST 2012
Author: gclayton
Date: Thu Jan 19 19:31:24 2012
New Revision: 148523
URL: http://llvm.org/viewvc/llvm-project?rev=148523&view=rev
Log:
Added a new tool that can be loaded into a user space darwin application and allows you
to find data on the heap. To use this, make the project and then when stopped in your
lldb debug session:
(lldb) process load /path/to/libheap.dylib
(lldb) find_pointer_in_heap (0x112233000000)
This will grep everything in all active allocation blocks and print and malloc blocks that contain the pointer 0x112233000000.
This can also work for c strings:
(lldb) find_cstring_in_heap ("hello")
Added:
lldb/trunk/examples/darwin/
lldb/trunk/examples/darwin/heap_find/
lldb/trunk/examples/darwin/heap_find/Makefile
lldb/trunk/examples/darwin/heap_find/heap_find.c
Added: lldb/trunk/examples/darwin/heap_find/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/Makefile?rev=148523&view=auto
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/Makefile (added)
+++ lldb/trunk/examples/darwin/heap_find/Makefile Thu Jan 19 19:31:24 2012
@@ -0,0 +1,7 @@
+LEVEL = ../../../test/make
+
+DYLIB_NAME := heap
+DYLIB_ONLY := YES
+DYLIB_C_SOURCES := heap_find.c
+
+include $(LEVEL)/Makefile.rules
Added: lldb/trunk/examples/darwin/heap_find/heap_find.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap_find.c?rev=148523&view=auto
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap_find.c (added)
+++ lldb/trunk/examples/darwin/heap_find/heap_find.c Thu Jan 19 19:31:24 2012
@@ -0,0 +1,193 @@
+#include <assert.h>
+#include <ctype.h>
+#include <mach/mach.h>
+#include <malloc/malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct range_callback_info_t;
+
+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 struct range_callback_info_tag
+{
+ zone_callback_t *zone_callback;
+ range_callback_t *range_callback;
+ void *baton;
+} range_callback_info_t;
+
+typedef enum data_type
+{
+ eDataTypeBytes,
+ eDataTypeCStr,
+ eDataTypeInteger
+} data_type_t;
+
+typedef struct range_contains_data_callback_info_tag
+{
+ const uint8_t *data;
+ const size_t data_len;
+ const uint32_t align;
+ const data_type_t data_type;
+ uint32_t match_count;
+} range_contains_data_callback_info_t;
+
+
+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)
+{
+ //printf ("foreach_zone_in_this_process ( info->zone_callback = %p, info->range_callback = %p, info->baton = %p)", info->zone_callback, info->range_callback, info->baton);
+ if (info == NULL || info->zone_callback == NULL)
+ return;
+
+ 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]);
+ }
+ }
+}
+
+static void
+range_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
+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);
+}
+
+const void
+foreach_range_in_this_process (range_callback_t *callback, void *baton)
+{
+ range_callback_info_t info = { enumerate_range_in_zone, callback ? callback : range_callback, baton };
+ foreach_zone_in_this_process (&info);
+}
+
+static void
+range_contains_ptr_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, uint64_t ptr_size)
+{
+ uint8_t *data = NULL;
+ range_contains_data_callback_info_t *data_info = (range_contains_data_callback_info_t *)baton;
+ if (data_info->data_len <= 0)
+ {
+ printf ("error: invalid data size: %zu\n", data_info->data_len);
+ }
+ else if (data_info->data_len > ptr_size)
+ {
+ // This block is too short to contain the data we are looking for...
+ return;
+ }
+ else if (task_peek (task, ptr_addr, ptr_size, (void **)&data) == KERN_SUCCESS)
+ {
+ assert (data);
+ const uint64_t end_addr = ptr_addr + ptr_size;
+ for (uint64_t addr = ptr_addr;
+ addr < end_addr && ((end_addr - addr) >= data_info->data_len);
+ addr += data_info->align, data += data_info->align)
+ {
+ if (memcmp (data_info->data, data, data_info->data_len) == 0)
+ {
+ ++data_info->match_count;
+ printf ("0x%llx: ", addr);
+ uint32_t i;
+ switch (data_info->data_type)
+ {
+ case eDataTypeInteger:
+ {
+ // NOTE: little endian specific, but all darwin platforms are little endian now..
+ for (i=0; i<data_info->data_len; ++i)
+ printf (i ? "%2.2x" : "0x%2.2x", data[data_info->data_len - (i + 1)]);
+ }
+ break;
+ case eDataTypeBytes:
+ {
+ for (i=0; i<data_info->data_len; ++i)
+ printf (" %2.2x", data[i]);
+ }
+ break;
+ case eDataTypeCStr:
+ {
+ putchar ('"');
+ for (i=0; i<data_info->data_len; ++i)
+ {
+ if (isprint (data[i]))
+ putchar (data[i]);
+ else
+ printf ("\\x%2.2x", data[i]);
+ }
+ putchar ('"');
+ }
+ break;
+
+ }
+ printf (" found in malloc block 0x%llx + %llu (malloc_size = %llu)\n", ptr_addr, addr - ptr_addr, ptr_size);
+ }
+ }
+ }
+ else
+ {
+ printf ("0x%llx: error: couldn't read %llu bytes\n", ptr_addr, ptr_size);
+ }
+}
+
+uint32_t
+find_pointer_in_heap (intptr_t addr)
+{
+ range_contains_data_callback_info_t data_info = { (uint8_t *)&addr, sizeof(addr), sizeof(addr), eDataTypeInteger, 0};
+ range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info };
+ foreach_zone_in_this_process (&info);
+ return data_info.match_count;
+}
+
+uint32_t
+find_cstring_in_heap (const char *s)
+{
+ if (s && s[0])
+ {
+ range_contains_data_callback_info_t data_info = { (uint8_t *)s, strlen(s), 1, eDataTypeCStr, 0};
+ range_callback_info_t info = { enumerate_range_in_zone, range_contains_ptr_callback, &data_info };
+ foreach_zone_in_this_process (&info);
+ return data_info.match_count;
+ }
+ else
+ {
+ printf ("error: invalid argument (empty cstring)\n");
+ }
+ return 0;
+}
More information about the lldb-commits
mailing list