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