diff options
author | Greg Clayton <gclayton@apple.com> | 2012-04-11 16:27:06 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2012-04-11 16:27:06 +0000 |
commit | 804de01c333e37958e10cc2932ec47417826a43a (patch) | |
tree | 17713215a79522848961378d60ff22c4800e64b5 | |
parent | 6a0afeb9c8d64a4d814687083dadb036a1ec6bb8 (diff) | |
download | bcm5719-llvm-804de01c333e37958e10cc2932ec47417826a43a.tar.gz bcm5719-llvm-804de01c333e37958e10cc2932ec47417826a43a.zip |
Added a new "heap.py" module that adds a new command line command that can find values on the heap and print out the dynamic type of the malloc block that contains the data. I will be modifying this a bit more to tweak the output and make the output more useful.
llvm-svn: 154504
-rw-r--r-- | lldb/examples/darwin/heap_find/Makefile | 2 | ||||
-rw-r--r-- | lldb/examples/darwin/heap_find/heap.py | 131 | ||||
-rw-r--r-- | lldb/examples/darwin/heap_find/heap_find.cpp | 103 |
3 files changed, 195 insertions, 41 deletions
diff --git a/lldb/examples/darwin/heap_find/Makefile b/lldb/examples/darwin/heap_find/Makefile index 75fcbc82f09..1d0367480e9 100644 --- a/lldb/examples/darwin/heap_find/Makefile +++ b/lldb/examples/darwin/heap_find/Makefile @@ -2,6 +2,6 @@ LEVEL = ../../../test/make DYLIB_NAME := heap DYLIB_ONLY := YES -DYLIB_C_SOURCES := heap_find.cpp +DYLIB_CXX_SOURCES := heap_find.cpp include $(LEVEL)/Makefile.rules diff --git a/lldb/examples/darwin/heap_find/heap.py b/lldb/examples/darwin/heap_find/heap.py new file mode 100644 index 00000000000..e5405da201b --- /dev/null +++ b/lldb/examples/darwin/heap_find/heap.py @@ -0,0 +1,131 @@ +#!/usr/bin/python + +#---------------------------------------------------------------------- +# Be sure to add the python path that points to the LLDB shared library. +# +# # To use this in the embedded python interpreter using "lldb" just +# import it with the full path using the "command script import" +# command +# (lldb) command script import /path/to/heap.py +# +# For the shells csh, tcsh: +# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./heap.py ) +# +# For the shells sh, bash: +# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./heap.py +#---------------------------------------------------------------------- + +import lldb +import commands +import optparse +import shlex + +def heap_search(debugger, command, result, dict): + command_args = shlex.split(command) + usage = "usage: %prog [options] <PATH> [PATH ...]" + description='''This command lets you run the /bin/ls command from within lldb as a quick and easy example.''' + parser = optparse.OptionParser(description=description, prog='heap_search',usage=usage) + parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) + parser.add_option('-t', '--type', type='string', dest='type', help='the type of data to search for (defaults to "pointer")', default='pointer') + parser.add_option('-o', '--po', action='store_true', dest='po', default='print the object descriptions for any matches') + try: + (options, args) = parser.parse_args(command_args) + except: + return + + if args: + + for data in args: + if options.type == 'pointer': + ptr = int(data, 0) + expr = 'find_pointer_in_heap(0x%x)' % ptr + #print 'expr: %s' % expr + expr_sbvalue = lldb.frame.EvaluateExpression (expr) + if expr_sbvalue.error.Success(): + if expr_sbvalue.unsigned: + match_value = lldb.value(expr_sbvalue) + i = 0 + while 1: + match_entry = match_value[i]; i += 1 + malloc_addr = int(match_entry.addr) + if malloc_addr == 0: + break + malloc_size = int(match_entry.size) + offset = int(match_entry.offset) + dynamic_value = match_entry.addr.sbvalue.dynamic + # If the type is still 'void *' then we weren't able to figure + # out a dynamic type for the malloc_addr + type_name = dynamic_value.type.name + if type_name == 'void *': + if malloc_size == 4096: + error = lldb.SBError() + data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error)) + if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': + print 'found %s 0x%x in (autorelease object pool) 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, malloc_addr, malloc_size, offset) + continue + print 'found %s 0x%x in malloc block 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, malloc_addr, malloc_size, offset) + else: + print 'found %s 0x%x in (%s) 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, type_name, malloc_addr, malloc_size, offset) + if options.po: + desc = dynamic_value.GetObjectDescription() + if desc: + print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) + else: + print '%s 0x%x was not found in any malloc blocks' % (options.type, ptr) + else: + print expr_sbvalue.error + elif options.type == 'cstring': + expr = 'find_cstring_in_heap("%s")' % data + #print 'expr: %s' % expr + expr_sbvalue = lldb.frame.EvaluateExpression (expr) + if expr_sbvalue.error.Success(): + if expr_sbvalue.unsigned: + match_value = lldb.value(expr_sbvalue) + print match_value + i = 0 + while 1: + match_entry = match_value[i]; i += 1 + malloc_addr = int(match_entry.addr) + if malloc_addr == 0: + break + malloc_size = int(match_entry.size) + offset = int(match_entry.offset) + dynamic_value = match_entry.addr.sbvalue.dynamic + # If the type is still 'void *' then we weren't able to figure + # out a dynamic type for the malloc_addr + type_name = dynamic_value.type.name + if type_name == 'void *': + print 'found %s "%s" in malloc block 0x%x, malloc_size = %u, offset = %u' % (options.type, data, malloc_addr, malloc_size, offset) + else: + print 'found %s "%s" in (%s) 0x%x, malloc_size = %u, offset = %u' % (options.type, data, type_name, malloc_addr, malloc_size, offset) + if options.po: + desc = dynamic_value.GetObjectDescription() + if desc: + print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) + else: + print '%s "%s" was not found in any malloc blocks' % (options.type, data) + else: + print expr_sbvalue.error + + else: + print 'error: invalid type "%s"\nvalid values are "pointer", "cstring"' % options.type + sys.exit(1) + else: + print 'error: no arguments were given' + +if __name__ == '__main__': + # This script is being run from the command line, create a debugger in case we are + # going to use any debugger functions in our function. + lldb.debugger = lldb.SBDebugger.Create() + ls (sys.argv) + +def __lldb_init_module (debugger, dict): + # This initializer is being run from LLDB in the embedded command interpreter + # Add any commands contained in this module to LLDB + debugger.HandleCommand('process load /Volumes/work/gclayton/Documents/src/lldb/examples/darwin/heap_find/libheap.dylib') + debugger.HandleCommand('command script add -f heap.heap_search heap_search') + print '"heap_search" command installed, type "heap_search --help" for detailed help' + + + + diff --git a/lldb/examples/darwin/heap_find/heap_find.cpp b/lldb/examples/darwin/heap_find/heap_find.cpp index 15d8c77f52d..f98b40580ce 100644 --- a/lldb/examples/darwin/heap_find/heap_find.cpp +++ b/lldb/examples/darwin/heap_find/heap_find.cpp @@ -42,7 +42,7 @@ // 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 // 0x104000730: 0x0000000100002460 (void *)0x0000000100002488: MyString // @@ -71,6 +71,7 @@ #include <stack_logging.h> #include <stdio.h> #include <stdlib.h> +#include <vector> struct range_callback_info_t; @@ -91,15 +92,23 @@ enum data_type_t eDataTypeInteger }; -typedef struct range_contains_data_callback_info_tag +struct range_contains_data_callback_info_t { 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; +}; +struct malloc_match +{ + void *addr; + intptr_t size; + intptr_t offset; +}; + +std::vector<malloc_match> g_matches; static kern_return_t task_peek (task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory) @@ -166,6 +175,7 @@ foreach_range_in_this_process (range_callback_t *callback, void *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) { @@ -191,39 +201,41 @@ range_contains_ptr_callback (task_t task, void *baton, unsigned type, uint64_t p 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); + malloc_match match = { (void *)ptr_addr, ptr_size, addr - ptr_addr }; + g_matches.push_back(match); + // 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); } } } @@ -233,24 +245,35 @@ range_contains_ptr_callback (task_t task, void *baton, unsigned type, uint64_t p } } -uint32_t +malloc_match * find_pointer_in_heap (intptr_t addr) { + g_matches.clear(); 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; + if (g_matches.empty()) + return NULL; + malloc_match match = { NULL, 0, 0 }; + g_matches.push_back(match); + return g_matches.data(); } -uint32_t + +malloc_match * find_cstring_in_heap (const char *s) { if (s && s[0]) { + g_matches.clear(); 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; + if (g_matches.empty()) + return NULL; + malloc_match match = { NULL, 0, 0 }; + g_matches.push_back(match); + return g_matches.data(); } else { |