blob: f4020edc049d967bbf0ce7ca43e327986a18f1c3 [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 Clayton93e5ba52012-04-13 16:24:09 +000024def add_common_options(parser):
25 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
26 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
27 parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
28 parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
29
Greg Clayton96666442012-04-11 18:30:53 +000030def heap_search(options, arg_str):
31 expr = None
Greg Claytonbff78412012-04-12 18:57:36 +000032 arg_str_description = arg_str
Greg Clayton93e5ba52012-04-13 16:24:09 +000033 default_memory_format = "Y" # 'Y' is "bytes with ASCII" format
34 #memory_chunk_size = 1
Greg Clayton96666442012-04-11 18:30:53 +000035 if options.type == 'pointer':
Greg Claytonf5902cb2012-04-12 21:06:22 +000036 expr = 'find_pointer_in_heap((void *)%s)' % arg_str
Greg Claytonbff78412012-04-12 18:57:36 +000037 arg_str_description = 'malloc block containing pointer %s' % arg_str
Greg Clayton93e5ba52012-04-13 16:24:09 +000038 default_memory_format = "A" # 'A' is "address" format
39 #memory_chunk_size = lldb.process.GetAddressByteSize()
Greg Clayton96666442012-04-11 18:30:53 +000040 elif options.type == 'cstr':
41 expr = 'find_cstring_in_heap("%s")' % arg_str
Greg Claytonbff78412012-04-12 18:57:36 +000042 arg_str_description = 'malloc block containing "%s"' % arg_str
43 elif options.type == 'addr':
Greg Claytonf5902cb2012-04-12 21:06:22 +000044 expr = 'find_block_for_address((void *)%s)' % arg_str
Greg Claytonbff78412012-04-12 18:57:36 +000045 arg_str_description = 'malloc block for %s' % arg_str
Greg Clayton96666442012-04-11 18:30:53 +000046 else:
47 print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
48 return
49
50 expr_sbvalue = lldb.frame.EvaluateExpression (expr)
51 if expr_sbvalue.error.Success():
52 if expr_sbvalue.unsigned:
53 match_value = lldb.value(expr_sbvalue)
54 i = 0
55 while 1:
56 match_entry = match_value[i]; i += 1
57 malloc_addr = match_entry.addr.sbvalue.unsigned
58 if malloc_addr == 0:
59 break
60 malloc_size = int(match_entry.size)
61 offset = int(match_entry.offset)
62 dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
63 # If the type is still 'void *' then we weren't able to figure
64 # out a dynamic type for the malloc_addr
65 type_name = dynamic_value.type.name
Greg Claytonbff78412012-04-12 18:57:36 +000066 description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
67 if offset != 0:
68 description += ' + %u' % (offset)
69 description += ', size = %u' % (malloc_size)
Greg Clayton96666442012-04-11 18:30:53 +000070 if type_name == 'void *':
71 if options.type == 'pointer' and malloc_size == 4096:
72 error = lldb.SBError()
73 data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
74 if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
Greg Claytonbff78412012-04-12 18:57:36 +000075 description += ', type = (AUTORELEASE!)'
Greg Clayton93e5ba52012-04-13 16:24:09 +000076 print description
Greg Claytonbff78412012-04-12 18:57:36 +000077 else:
78 description += ', type = %s' % (type_name)
79 derefed_dynamic_value = dynamic_value.deref
80 ivar_member = None
81 if derefed_dynamic_value:
82 derefed_dynamic_type = derefed_dynamic_value.type
83 member = derefed_dynamic_type.GetFieldAtIndex(0)
84 search_bases = False
85 if member:
86 if member.GetOffsetInBytes() <= offset:
87 for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
88 member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
89 member_byte_offset = member.GetOffsetInBytes()
90 if member_byte_offset == offset:
91 ivar_member = member
92 break
93 else:
94 search_bases = True
Greg Clayton96666442012-04-11 18:30:53 +000095 else:
96 search_bases = True
Greg Clayton96666442012-04-11 18:30:53 +000097
Greg Claytonbff78412012-04-12 18:57:36 +000098 if not ivar_member and search_bases:
99 for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
100 member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
Greg Clayton96666442012-04-11 18:30:53 +0000101 member_byte_offset = member.GetOffsetInBytes()
102 if member_byte_offset == offset:
103 ivar_member = member
104 break
Greg Claytonbff78412012-04-12 18:57:36 +0000105 if not ivar_member:
106 for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
107 member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
108 member_byte_offset = member.GetOffsetInBytes()
109 if member_byte_offset == offset:
110 ivar_member = member
111 break
Greg Clayton96666442012-04-11 18:30:53 +0000112 if ivar_member:
Greg Claytonbff78412012-04-12 18:57:36 +0000113 description +=', ivar = %s' % (ivar_member.name)
114
115 print description
116 if derefed_dynamic_value:
117 print derefed_dynamic_value
118 if options.print_object_description:
119 desc = dynamic_value.GetObjectDescription()
120 if desc:
121 print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000122 if options.memory:
123 memory_format = options.format
124 if not memory_format:
125 memory_format = default_memory_format
126 cmd_result = lldb.SBCommandReturnObject()
127 #count = malloc_size / memory_chunk_size
128 memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size)
129 lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
130 print cmd_result.GetOutput()
Greg Clayton96666442012-04-11 18:30:53 +0000131 else:
132 print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
133 else:
Greg Claytonbff78412012-04-12 18:57:36 +0000134 print expr_sbvalue.error
135 print
Greg Clayton96666442012-04-11 18:30:53 +0000136
Greg Claytonbff78412012-04-12 18:57:36 +0000137def ptr_refs(debugger, command, result, dict):
Greg Claytone93e24f2012-04-11 16:27:06 +0000138 command_args = shlex.split(command)
Greg Claytonbff78412012-04-12 18:57:36 +0000139 usage = "usage: %prog [options] <PTR> [PTR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000140 description='''Searches the heap for pointer references on darwin user space programs.
141
142 Any matches that were found will dump the malloc blocks that contain the pointers
143 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000144 dynamic type information in the program.'''
145 parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000146 add_common_options(parser)
Greg Claytone93e24f2012-04-11 16:27:06 +0000147 try:
148 (options, args) = parser.parse_args(command_args)
149 except:
150 return
Greg Clayton96666442012-04-11 18:30:53 +0000151
152 options.type = 'pointer'
Greg Claytone93e24f2012-04-11 16:27:06 +0000153
154 if args:
155
156 for data in args:
Greg Clayton96666442012-04-11 18:30:53 +0000157 heap_search (options, data)
Greg Claytone93e24f2012-04-11 16:27:06 +0000158 else:
Greg Clayton96666442012-04-11 18:30:53 +0000159 print 'error: no pointer arguments were given'
Greg Claytone93e24f2012-04-11 16:27:06 +0000160
Greg Claytonbff78412012-04-12 18:57:36 +0000161def cstr_refs(debugger, command, result, dict):
Greg Clayton96666442012-04-11 18:30:53 +0000162 command_args = shlex.split(command)
Greg Claytonbff78412012-04-12 18:57:36 +0000163 usage = "usage: %prog [options] <CSTR> [CSTR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000164 description='''Searches the heap for C string references on darwin user space programs.
165
166 Any matches that were found will dump the malloc blocks that contain the C strings
167 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000168 dynamic type information in the program.'''
169 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000170 add_common_options(parser)
Greg Clayton96666442012-04-11 18:30:53 +0000171 try:
172 (options, args) = parser.parse_args(command_args)
173 except:
174 return
175
176 options.type = 'cstr'
177
178 if args:
179
180 for data in args:
181 heap_search (options, data)
182 else:
183 print 'error: no c string arguments were given to search for'
Greg Claytone93e24f2012-04-11 16:27:06 +0000184
Greg Claytonbff78412012-04-12 18:57:36 +0000185def malloc_info(debugger, command, result, dict):
186 command_args = shlex.split(command)
187 usage = "usage: %prog [options] <ADDR> [ADDR ...]"
188 description='''Searches the heap a malloc block that contains the addresses specified as arguments.
189
190 Any matches that were found will dump the malloc blocks that match or contain
191 the specified address. The matching blocks might be able to show what kind
192 of objects they are using dynamic type information in the program.'''
193 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000194 add_common_options(parser)
Greg Claytonbff78412012-04-12 18:57:36 +0000195 try:
196 (options, args) = parser.parse_args(command_args)
197 except:
198 return
199
200 options.type = 'addr'
201
202 if args:
203
204 for data in args:
205 heap_search (options, data)
206 else:
207 print 'error: no c string arguments were given to search for'
208
Greg Claytone93e24f2012-04-11 16:27:06 +0000209def __lldb_init_module (debugger, dict):
210 # This initializer is being run from LLDB in the embedded command interpreter
211 # Add any commands contained in this module to LLDB
Greg Clayton96666442012-04-11 18:30:53 +0000212 libheap_dylib_path = os.path.dirname(__file__) + '/libheap.dylib'
213 debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
Greg Claytonbff78412012-04-12 18:57:36 +0000214 debugger.HandleCommand('command script add -f heap.ptr_refs ptr_refs')
215 debugger.HandleCommand('command script add -f heap.cstr_refs cstr_refs')
216 debugger.HandleCommand('command script add -f heap.malloc_info malloc_info')
217 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 +0000218
219
220
221