blob: 982165e90bacae0f9ea1476ccc263b04be4ef5b1 [file] [log] [blame]
Greg Claytone93e24f2012-04-11 16:27:06 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
4# Be sure to add the python path that points to the LLDB shared library.
5#
6# # To use this in the embedded python interpreter using "lldb" just
7# import it with the full path using the "command script import"
8# command
9# (lldb) command script import /path/to/heap.py
10#
11# For the shells csh, tcsh:
12# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./heap.py )
13#
14# For the shells sh, bash:
15# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./heap.py
16#----------------------------------------------------------------------
17
18import lldb
19import commands
20import optparse
Greg Clayton96666442012-04-11 18:30:53 +000021import os
Greg Claytone93e24f2012-04-11 16:27:06 +000022import shlex
23
Greg Clayton96666442012-04-11 18:30:53 +000024def heap_search(options, arg_str):
25 expr = None
Greg Claytonbff78412012-04-12 18:57:36 +000026 arg_str_description = arg_str
Greg Clayton96666442012-04-11 18:30:53 +000027 if options.type == 'pointer':
Greg Claytonbff78412012-04-12 18:57:36 +000028 expr = 'find_pointer_in_heap(%s)' % arg_str
29 arg_str_description = 'malloc block containing pointer %s' % arg_str
Greg Clayton96666442012-04-11 18:30:53 +000030 elif options.type == 'cstr':
31 expr = 'find_cstring_in_heap("%s")' % arg_str
Greg Claytonbff78412012-04-12 18:57:36 +000032 arg_str_description = 'malloc block containing "%s"' % arg_str
33 elif options.type == 'addr':
34 expr = 'find_block_for_address(%s)' % arg_str
35 arg_str_description = 'malloc block for %s' % arg_str
Greg Clayton96666442012-04-11 18:30:53 +000036 else:
37 print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
38 return
39
40 expr_sbvalue = lldb.frame.EvaluateExpression (expr)
41 if expr_sbvalue.error.Success():
42 if expr_sbvalue.unsigned:
43 match_value = lldb.value(expr_sbvalue)
44 i = 0
45 while 1:
46 match_entry = match_value[i]; i += 1
47 malloc_addr = match_entry.addr.sbvalue.unsigned
48 if malloc_addr == 0:
49 break
50 malloc_size = int(match_entry.size)
51 offset = int(match_entry.offset)
52 dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
53 # If the type is still 'void *' then we weren't able to figure
54 # out a dynamic type for the malloc_addr
55 type_name = dynamic_value.type.name
Greg Claytonbff78412012-04-12 18:57:36 +000056 description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
57 if offset != 0:
58 description += ' + %u' % (offset)
59 description += ', size = %u' % (malloc_size)
Greg Clayton96666442012-04-11 18:30:53 +000060 if type_name == 'void *':
61 if options.type == 'pointer' and malloc_size == 4096:
62 error = lldb.SBError()
63 data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
64 if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
Greg Claytonbff78412012-04-12 18:57:36 +000065 description += ', type = (AUTORELEASE!)'
66 print description
Greg Clayton96666442012-04-11 18:30:53 +000067 continue
Greg Claytonbff78412012-04-12 18:57:36 +000068 else:
69 description += ', type = %s' % (type_name)
70 derefed_dynamic_value = dynamic_value.deref
71 ivar_member = None
72 if derefed_dynamic_value:
73 derefed_dynamic_type = derefed_dynamic_value.type
74 member = derefed_dynamic_type.GetFieldAtIndex(0)
75 search_bases = False
76 if member:
77 if member.GetOffsetInBytes() <= offset:
78 for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
79 member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
80 member_byte_offset = member.GetOffsetInBytes()
81 if member_byte_offset == offset:
82 ivar_member = member
83 break
84 else:
85 search_bases = True
Greg Clayton96666442012-04-11 18:30:53 +000086 else:
87 search_bases = True
Greg Clayton96666442012-04-11 18:30:53 +000088
Greg Claytonbff78412012-04-12 18:57:36 +000089 if not ivar_member and search_bases:
90 for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
91 member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
Greg Clayton96666442012-04-11 18:30:53 +000092 member_byte_offset = member.GetOffsetInBytes()
93 if member_byte_offset == offset:
94 ivar_member = member
95 break
Greg Claytonbff78412012-04-12 18:57:36 +000096 if not ivar_member:
97 for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
98 member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
99 member_byte_offset = member.GetOffsetInBytes()
100 if member_byte_offset == offset:
101 ivar_member = member
102 break
Greg Clayton96666442012-04-11 18:30:53 +0000103 if ivar_member:
Greg Claytonbff78412012-04-12 18:57:36 +0000104 description +=', ivar = %s' % (ivar_member.name)
105
106 print description
107 if derefed_dynamic_value:
108 print derefed_dynamic_value
109 if options.print_object_description:
110 desc = dynamic_value.GetObjectDescription()
111 if desc:
112 print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
Greg Clayton96666442012-04-11 18:30:53 +0000113 else:
114 print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
115 else:
Greg Claytonbff78412012-04-12 18:57:36 +0000116 print expr_sbvalue.error
117 print
Greg Clayton96666442012-04-11 18:30:53 +0000118
Greg Claytonbff78412012-04-12 18:57:36 +0000119def ptr_refs(debugger, command, result, dict):
Greg Claytone93e24f2012-04-11 16:27:06 +0000120 command_args = shlex.split(command)
Greg Claytonbff78412012-04-12 18:57:36 +0000121 usage = "usage: %prog [options] <PTR> [PTR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000122 description='''Searches the heap for pointer references on darwin user space programs.
123
124 Any matches that were found will dump the malloc blocks that contain the pointers
125 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000126 dynamic type information in the program.'''
127 parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
Greg Claytone93e24f2012-04-11 16:27:06 +0000128 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
Greg Clayton96666442012-04-11 18:30:53 +0000129 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
Greg Claytonbff78412012-04-12 18:57:36 +0000130 parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False)
Greg Claytone93e24f2012-04-11 16:27:06 +0000131 try:
132 (options, args) = parser.parse_args(command_args)
133 except:
134 return
Greg Clayton96666442012-04-11 18:30:53 +0000135
136 options.type = 'pointer'
Greg Claytone93e24f2012-04-11 16:27:06 +0000137
138 if args:
139
140 for data in args:
Greg Clayton96666442012-04-11 18:30:53 +0000141 heap_search (options, data)
Greg Claytone93e24f2012-04-11 16:27:06 +0000142 else:
Greg Clayton96666442012-04-11 18:30:53 +0000143 print 'error: no pointer arguments were given'
Greg Claytone93e24f2012-04-11 16:27:06 +0000144
Greg Claytonbff78412012-04-12 18:57:36 +0000145def cstr_refs(debugger, command, result, dict):
Greg Clayton96666442012-04-11 18:30:53 +0000146 command_args = shlex.split(command)
Greg Claytonbff78412012-04-12 18:57:36 +0000147 usage = "usage: %prog [options] <CSTR> [CSTR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000148 description='''Searches the heap for C string references on darwin user space programs.
149
150 Any matches that were found will dump the malloc blocks that contain the C strings
151 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000152 dynamic type information in the program.'''
153 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Clayton96666442012-04-11 18:30:53 +0000154 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
155 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
Greg Claytonbff78412012-04-12 18:57:36 +0000156 parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False)
Greg Clayton96666442012-04-11 18:30:53 +0000157 try:
158 (options, args) = parser.parse_args(command_args)
159 except:
160 return
161
162 options.type = 'cstr'
163
164 if args:
165
166 for data in args:
167 heap_search (options, data)
168 else:
169 print 'error: no c string arguments were given to search for'
Greg Claytone93e24f2012-04-11 16:27:06 +0000170
Greg Claytonbff78412012-04-12 18:57:36 +0000171def malloc_info(debugger, command, result, dict):
172 command_args = shlex.split(command)
173 usage = "usage: %prog [options] <ADDR> [ADDR ...]"
174 description='''Searches the heap a malloc block that contains the addresses specified as arguments.
175
176 Any matches that were found will dump the malloc blocks that match or contain
177 the specified address. The matching blocks might be able to show what kind
178 of objects they are using dynamic type information in the program.'''
179 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
180 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
181 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
182 parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False)
183 try:
184 (options, args) = parser.parse_args(command_args)
185 except:
186 return
187
188 options.type = 'addr'
189
190 if args:
191
192 for data in args:
193 heap_search (options, data)
194 else:
195 print 'error: no c string arguments were given to search for'
196
Greg Claytone93e24f2012-04-11 16:27:06 +0000197def __lldb_init_module (debugger, dict):
198 # This initializer is being run from LLDB in the embedded command interpreter
199 # Add any commands contained in this module to LLDB
Greg Clayton96666442012-04-11 18:30:53 +0000200 libheap_dylib_path = os.path.dirname(__file__) + '/libheap.dylib'
201 debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
Greg Claytonbff78412012-04-12 18:57:36 +0000202 debugger.HandleCommand('command script add -f heap.ptr_refs ptr_refs')
203 debugger.HandleCommand('command script add -f heap.cstr_refs cstr_refs')
204 debugger.HandleCommand('command script add -f heap.malloc_info malloc_info')
205 print '"ptr_refs", "cstr_refs", and "malloc_info" commands have been installed, use the "--help" options on these commands for detailed help.'
Greg Claytone93e24f2012-04-11 16:27:06 +0000206
207
208
209