heap.py revision e93e24fb12f05cf363bc99e9c792c28cacace0c3
1e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#!/usr/bin/python 2e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 3e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 4e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# Be sure to add the python path that points to the LLDB shared library. 5e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 6e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# # To use this in the embedded python interpreter using "lldb" just 7e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# import it with the full path using the "command script import" 8e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# command 9e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# (lldb) command script import /path/to/heap.py 10e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 11e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# For the shells csh, tcsh: 12e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./heap.py ) 13e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 14e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# For the shells sh, bash: 15e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./heap.py 16e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 17e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 18e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport lldb 19e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport commands 20e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport optparse 21e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport shlex 22e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 23e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytondef heap_search(debugger, command, result, dict): 24e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton command_args = shlex.split(command) 25e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton usage = "usage: %prog [options] <PATH> [PATH ...]" 26e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton description='''This command lets you run the /bin/ls command from within lldb as a quick and easy example.''' 27e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton parser = optparse.OptionParser(description=description, prog='heap_search',usage=usage) 28e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 29e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton parser.add_option('-t', '--type', type='string', dest='type', help='the type of data to search for (defaults to "pointer")', default='pointer') 30e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton parser.add_option('-o', '--po', action='store_true', dest='po', default='print the object descriptions for any matches') 31e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton try: 32e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton (options, args) = parser.parse_args(command_args) 33e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton except: 34e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton return 35e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 36e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if args: 37e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 38e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton for data in args: 39e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if options.type == 'pointer': 40e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton ptr = int(data, 0) 41e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton expr = 'find_pointer_in_heap(0x%x)' % ptr 42e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton #print 'expr: %s' % expr 43e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton expr_sbvalue = lldb.frame.EvaluateExpression (expr) 44e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if expr_sbvalue.error.Success(): 45e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if expr_sbvalue.unsigned: 46e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton match_value = lldb.value(expr_sbvalue) 47e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton i = 0 48e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton while 1: 49e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton match_entry = match_value[i]; i += 1 50e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton malloc_addr = int(match_entry.addr) 51e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if malloc_addr == 0: 52e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton break 53e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton malloc_size = int(match_entry.size) 54e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton offset = int(match_entry.offset) 55e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton dynamic_value = match_entry.addr.sbvalue.dynamic 56e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # If the type is still 'void *' then we weren't able to figure 57e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # out a dynamic type for the malloc_addr 58e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton type_name = dynamic_value.type.name 59e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if type_name == 'void *': 60e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if malloc_size == 4096: 61e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton error = lldb.SBError() 62e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error)) 63e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': 64e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'found %s 0x%x in (autorelease object pool) 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, malloc_addr, malloc_size, offset) 65e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton continue 66e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'found %s 0x%x in malloc block 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, malloc_addr, malloc_size, offset) 67e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 68e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'found %s 0x%x in (%s) 0x%x, malloc_size = %u, offset = %u' % (options.type, ptr, type_name, malloc_addr, malloc_size, offset) 69e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if options.po: 70e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton desc = dynamic_value.GetObjectDescription() 71e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if desc: 72e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) 73e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 74e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print '%s 0x%x was not found in any malloc blocks' % (options.type, ptr) 75e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 76e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print expr_sbvalue.error 77e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton elif options.type == 'cstring': 78e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton expr = 'find_cstring_in_heap("%s")' % data 79e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton #print 'expr: %s' % expr 80e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton expr_sbvalue = lldb.frame.EvaluateExpression (expr) 81e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if expr_sbvalue.error.Success(): 82e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if expr_sbvalue.unsigned: 83e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton match_value = lldb.value(expr_sbvalue) 84e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print match_value 85e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton i = 0 86e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton while 1: 87e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton match_entry = match_value[i]; i += 1 88e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton malloc_addr = int(match_entry.addr) 89e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if malloc_addr == 0: 90e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton break 91e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton malloc_size = int(match_entry.size) 92e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton offset = int(match_entry.offset) 93e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton dynamic_value = match_entry.addr.sbvalue.dynamic 94e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # If the type is still 'void *' then we weren't able to figure 95e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # out a dynamic type for the malloc_addr 96e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton type_name = dynamic_value.type.name 97e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if type_name == 'void *': 98e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'found %s "%s" in malloc block 0x%x, malloc_size = %u, offset = %u' % (options.type, data, malloc_addr, malloc_size, offset) 99e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 100e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'found %s "%s" in (%s) 0x%x, malloc_size = %u, offset = %u' % (options.type, data, type_name, malloc_addr, malloc_size, offset) 101e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if options.po: 102e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton desc = dynamic_value.GetObjectDescription() 103e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if desc: 104e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) 105e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 106e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print '%s "%s" was not found in any malloc blocks' % (options.type, data) 107e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 108e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print expr_sbvalue.error 109e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 110e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 111e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'error: invalid type "%s"\nvalid values are "pointer", "cstring"' % options.type 112e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton sys.exit(1) 113e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 114e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print 'error: no arguments were given' 115e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 116e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonif __name__ == '__main__': 117e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # This script is being run from the command line, create a debugger in case we are 118e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # going to use any debugger functions in our function. 119e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton lldb.debugger = lldb.SBDebugger.Create() 120e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton ls (sys.argv) 121e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 122e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytondef __lldb_init_module (debugger, dict): 123e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # This initializer is being run from LLDB in the embedded command interpreter 124e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # Add any commands contained in this module to LLDB 125e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton debugger.HandleCommand('process load /Volumes/work/gclayton/Documents/src/lldb/examples/darwin/heap_find/libheap.dylib') 126e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton debugger.HandleCommand('command script add -f heap.heap_search heap_search') 127e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton print '"heap_search" command installed, type "heap_search --help" for detailed help' 128e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 129e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 130e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 131e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 132