blob: 3a04846e6d7c1f2f1fd856e79c2a033c48a2b9b2 [file] [log] [blame]
Greg Clayton804de012012-04-11 16:27:06 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
Greg Claytond712ef02012-04-25 18:40:20 +00004# This module is designed to live inside the "lldb" python package
5# in the "lldb.macosx" package. To use this in the embedded python
6# interpreter using "lldb" just import it:
Greg Clayton804de012012-04-11 16:27:06 +00007#
Greg Claytond712ef02012-04-25 18:40:20 +00008# (lldb) script import lldb.macosx.heap
Greg Clayton804de012012-04-11 16:27:06 +00009#----------------------------------------------------------------------
10
11import lldb
12import commands
13import optparse
Greg Clayton7fb671b2012-04-11 18:30:53 +000014import os
Greg Claytond712ef02012-04-25 18:40:20 +000015import os.path
Greg Claytone04cfd22012-07-11 22:13:18 +000016import re
Greg Clayton804de012012-04-11 16:27:06 +000017import shlex
Greg Claytond712ef02012-04-25 18:40:20 +000018import string
19import tempfile
Greg Claytoned3eee62012-04-25 01:49:50 +000020import lldb.utils.symbolication
Greg Clayton804de012012-04-11 16:27:06 +000021
Greg Claytond712ef02012-04-25 18:40:20 +000022g_libheap_dylib_dir = None
23g_libheap_dylib_dict = dict()
Greg Clayton341039f2012-05-11 02:42:36 +000024g_verbose = False
Greg Claytond712ef02012-04-25 18:40:20 +000025
Greg Claytonb403a152012-04-21 00:11:26 +000026def load_dylib():
27 if lldb.target:
Greg Claytond712ef02012-04-25 18:40:20 +000028 global g_libheap_dylib_dir
29 global g_libheap_dylib_dict
30 triple = lldb.target.triple
Greg Clayton4f76fef2012-04-25 21:23:07 +000031 if triple in g_libheap_dylib_dict:
32 libheap_dylib_path = g_libheap_dylib_dict[triple]
33 else:
Greg Claytond712ef02012-04-25 18:40:20 +000034 if not g_libheap_dylib_dir:
Greg Clayton4f76fef2012-04-25 21:23:07 +000035 g_libheap_dylib_dir = tempfile.gettempdir() + '/lldb-dylibs'
36 triple_dir = g_libheap_dylib_dir + '/' + triple + '/' + __name__
Greg Claytond712ef02012-04-25 18:40:20 +000037 if not os.path.exists(triple_dir):
Greg Clayton4f76fef2012-04-25 21:23:07 +000038 os.makedirs(triple_dir)
Greg Claytond712ef02012-04-25 18:40:20 +000039 libheap_dylib_path = triple_dir + '/libheap.dylib'
40 g_libheap_dylib_dict[triple] = libheap_dylib_path
Greg Clayton4f76fef2012-04-25 21:23:07 +000041 heap_code_directory = os.path.dirname(__file__) + '/heap'
42 heap_source_file = heap_code_directory + '/heap_find.cpp'
43 # Check if the dylib doesn't exist, or if "heap_find.cpp" is newer than the dylib
44 if not os.path.exists(libheap_dylib_path) or os.stat(heap_source_file).st_mtime > os.stat(libheap_dylib_path).st_mtime:
45 # Remake the dylib
Greg Claytond712ef02012-04-25 18:40:20 +000046 make_command = '(cd "%s" ; make EXE="%s" ARCH=%s)' % (heap_code_directory, libheap_dylib_path, string.split(triple, '-')[0])
Greg Clayton89d4f332012-06-27 19:57:59 +000047 (make_exit_status, make_output) = commands.getstatusoutput(make_command)
48 if make_exit_status != 0:
Greg Claytonc373ca52012-09-01 00:34:35 +000049 return 'error: make failed: %s' % (make_output)
Greg Claytonb403a152012-04-21 00:11:26 +000050 if os.path.exists(libheap_dylib_path):
51 libheap_dylib_spec = lldb.SBFileSpec(libheap_dylib_path)
52 if lldb.target.FindModule(libheap_dylib_spec):
53 return None # success, 'libheap.dylib' already loaded
54 if lldb.process:
55 state = lldb.process.state
56 if state == lldb.eStateStopped:
57 (libheap_dylib_path)
58 error = lldb.SBError()
59 image_idx = lldb.process.LoadImage(libheap_dylib_spec, error)
60 if error.Success():
61 return None
62 else:
63 if error:
64 return 'error: %s' % error
65 else:
66 return 'error: "process load \'%s\'" failed' % libheap_dylib_spec
67 else:
68 return 'error: process is not stopped'
69 else:
70 return 'error: invalid process'
71 else:
72 return 'error: file does not exist "%s"' % libheap_dylib_path
73 else:
74 return 'error: invalid target'
75
76 debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
Greg Clayton341039f2012-05-11 02:42:36 +000077 if lldb.target.FindModule(libheap_dylib_spec):
78 return None # success, 'libheap.dylib' already loaded
79 return 'error: failed to load "%s"' % libheap_dylib_path
Greg Clayton94073022012-07-07 01:22:45 +000080
81def get_member_types_for_offset(value_type, offset, member_list):
82 member = value_type.GetFieldAtIndex(0)
83 search_bases = False
84 if member:
85 if member.GetOffsetInBytes() <= offset:
86 for field_idx in range (value_type.GetNumberOfFields()):
87 member = value_type.GetFieldAtIndex(field_idx)
88 member_byte_offset = member.GetOffsetInBytes()
89 member_end_byte_offset = member_byte_offset + member.type.size
90 if member_byte_offset <= offset and offset < member_end_byte_offset:
91 member_list.append(member)
92 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
93 return
94 else:
95 search_bases = True
96 else:
97 search_bases = True
98 if search_bases:
99 for field_idx in range (value_type.GetNumberOfDirectBaseClasses()):
100 member = value_type.GetDirectBaseClassAtIndex(field_idx)
101 member_byte_offset = member.GetOffsetInBytes()
102 member_end_byte_offset = member_byte_offset + member.type.size
103 if member_byte_offset <= offset and offset < member_end_byte_offset:
104 member_list.append(member)
105 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
106 return
107 for field_idx in range (value_type.GetNumberOfVirtualBaseClasses()):
108 member = value_type.GetVirtualBaseClassAtIndex(field_idx)
109 member_byte_offset = member.GetOffsetInBytes()
110 member_end_byte_offset = member_byte_offset + member.type.size
111 if member_byte_offset <= offset and offset < member_end_byte_offset:
112 member_list.append(member)
113 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
114 return
Greg Claytone04cfd22012-07-11 22:13:18 +0000115
116def append_regex_callback(option, opt, value, parser):
117 try:
118 ivar_regex = re.compile(value)
119 parser.values.ivar_regex_blacklist.append(ivar_regex)
120 except:
121 print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
Greg Claytonb403a152012-04-21 00:11:26 +0000122
Greg Claytond84bb482012-04-13 16:24:09 +0000123def add_common_options(parser):
124 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
Greg Claytone04cfd22012-07-11 22:13:18 +0000125 parser.add_option('-t', '--type', action='store_true', dest='print_type', help='print the full value of the type for each matching malloc block', default=False)
Greg Claytond84bb482012-04-13 16:24:09 +0000126 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
127 parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
128 parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
Greg Claytone04cfd22012-07-11 22:13:18 +0000129 parser.add_option('-I', '--omit-ivar-regex', type='string', action='callback', callback=append_regex_callback, dest='ivar_regex_blacklist', default=[], help='specify one or more regular expressions used to backlist any matches that are in ivars')
Greg Claytonb403a152012-04-21 00:11:26 +0000130 parser.add_option('-s', '--stack', action='store_true', dest='stack', help='gets the stack that allocated each malloc block if MallocStackLogging is enabled', default=False)
Greg Claytond9fc5352012-05-10 23:17:28 +0000131 parser.add_option('-S', '--stack-history', action='store_true', dest='stack_history', help='gets the stack history for all allocations whose start address matches each malloc block if MallocStackLogging is enabled', default=False)
Greg Claytone04cfd22012-07-11 22:13:18 +0000132 parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=256)
Greg Clayton774ebdf2012-08-11 02:26:26 +0000133 parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1)
Greg Claytond9fc5352012-05-10 23:17:28 +0000134
Greg Claytonc373ca52012-09-01 00:34:35 +0000135def dump_stack_history_entry(result, stack_history_entry, idx):
Greg Clayton7200ed12012-05-10 23:37:52 +0000136 address = int(stack_history_entry.address)
137 if address:
138 type_flags = int(stack_history_entry.type_flags)
Greg Claytond9fc5352012-05-10 23:17:28 +0000139 symbolicator = lldb.utils.symbolication.Symbolicator()
140 symbolicator.target = lldb.target
Greg Clayton341039f2012-05-11 02:42:36 +0000141 type_str = ''
142 if type_flags == 0:
143 type_str = 'free'
144 else:
145 if type_flags & 2:
146 type_str = 'alloc'
147 elif type_flags & 4:
148 type_str = 'free'
149 elif type_flags & 1:
150 type_str = 'generic'
151 else:
152 type_str = hex(type_flags)
Greg Claytonc373ca52012-09-01 00:34:35 +0000153 result.AppendMessage('stack[%u]: addr = 0x%x, type=%s, frames:' % (idx, address, type_str))
Greg Claytond9fc5352012-05-10 23:17:28 +0000154 frame_idx = 0
Greg Clayton7200ed12012-05-10 23:37:52 +0000155 idx = 0
156 pc = int(stack_history_entry.frames[idx])
Greg Claytond9fc5352012-05-10 23:17:28 +0000157 while pc != 0:
158 if pc >= 0x1000:
159 frames = symbolicator.symbolicate(pc)
160 if frames:
161 for frame in frames:
Greg Claytonc373ca52012-09-01 00:34:35 +0000162 result.AppendMessage(' [%u] %s' % (frame_idx, frame))
Greg Claytond9fc5352012-05-10 23:17:28 +0000163 frame_idx += 1
164 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000165 result.AppendMessage(' [%u] 0x%x' % (frame_idx, pc))
Greg Claytond9fc5352012-05-10 23:17:28 +0000166 frame_idx += 1
Greg Clayton7200ed12012-05-10 23:37:52 +0000167 idx = idx + 1
168 pc = int(stack_history_entry.frames[idx])
Greg Claytond9fc5352012-05-10 23:17:28 +0000169 else:
170 pc = 0
Greg Claytonc373ca52012-09-01 00:34:35 +0000171 result.AppendMessage('')
Greg Claytond9fc5352012-05-10 23:17:28 +0000172
Greg Claytonc373ca52012-09-01 00:34:35 +0000173def dump_stack_history_entries(result, addr, history):
Greg Claytond9fc5352012-05-10 23:17:28 +0000174 # malloc_stack_entry *get_stack_history_for_address (const void * addr)
Greg Clayton341039f2012-05-11 02:42:36 +0000175 expr = 'get_stack_history_for_address((void *)0x%x, %u)' % (addr, history)
Greg Claytond9fc5352012-05-10 23:17:28 +0000176 expr_sbvalue = lldb.frame.EvaluateExpression (expr)
177 if expr_sbvalue.error.Success():
178 if expr_sbvalue.unsigned:
179 expr_value = lldb.value(expr_sbvalue)
180 idx = 0;
181 stack_history_entry = expr_value[idx]
Greg Clayton7200ed12012-05-10 23:37:52 +0000182 while int(stack_history_entry.address) != 0:
Greg Claytonc373ca52012-09-01 00:34:35 +0000183 dump_stack_history_entry(result, stack_history_entry, idx)
Greg Claytond9fc5352012-05-10 23:17:28 +0000184 idx = idx + 1
185 stack_history_entry = expr_value[idx]
Greg Claytonc373ca52012-09-01 00:34:35 +0000186 else:
187 result.AppendMessage('"%s" returned zero' % (expr))
Greg Clayton341039f2012-05-11 02:42:36 +0000188 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000189 result.AppendMessage('error: expression failed "%s" => %s' % (expr, expr_sbvalue.error))
Greg Claytond9fc5352012-05-10 23:17:28 +0000190
Greg Claytone04cfd22012-07-11 22:13:18 +0000191
Greg Claytonc373ca52012-09-01 00:34:35 +0000192def display_match_results (result, options, arg_str_description, expr_sbvalue, print_no_matches = True):
Greg Clayton7fb671b2012-04-11 18:30:53 +0000193 if expr_sbvalue.error.Success():
194 if expr_sbvalue.unsigned:
195 match_value = lldb.value(expr_sbvalue)
196 i = 0
Greg Clayton774ebdf2012-08-11 02:26:26 +0000197 match_idx = 0
Greg Clayton7fb671b2012-04-11 18:30:53 +0000198 while 1:
Greg Claytone04cfd22012-07-11 22:13:18 +0000199 print_entry = True
Greg Clayton7fb671b2012-04-11 18:30:53 +0000200 match_entry = match_value[i]; i += 1
Greg Claytone04cfd22012-07-11 22:13:18 +0000201 if i >= options.max_matches:
Greg Claytonc373ca52012-09-01 00:34:35 +0000202 result.AppendMessage('error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches))
Greg Claytone04cfd22012-07-11 22:13:18 +0000203 break
Greg Clayton7fb671b2012-04-11 18:30:53 +0000204 malloc_addr = match_entry.addr.sbvalue.unsigned
205 if malloc_addr == 0:
206 break
207 malloc_size = int(match_entry.size)
208 offset = int(match_entry.offset)
Greg Clayton774ebdf2012-08-11 02:26:26 +0000209
210 if options.offset >= 0 and options.offset != offset:
211 print_entry = False
212 else:
213 match_addr = malloc_addr + offset
214 dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
215 description = '[%u] %s: addr = 0x%x' % (match_idx, arg_str_description, malloc_addr)
216 if offset != 0:
217 description += ' + %u' % (offset)
218 description += ', size = %u' % (malloc_size)
219 derefed_dynamic_value = None
220 if dynamic_value.type.name == 'void *':
221 if options.type == 'pointer' and malloc_size == 4096:
222 error = lldb.SBError()
223 data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
224 if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
225 description += ', type = (AUTORELEASE!)'
226 else:
227 derefed_dynamic_value = dynamic_value.deref
228 if derefed_dynamic_value:
229 derefed_dynamic_type = derefed_dynamic_value.type
230 derefed_dynamic_type_size = derefed_dynamic_type.size
231 derefed_dynamic_type_name = derefed_dynamic_type.name
232 description += ', type = %s <%u>' % (derefed_dynamic_type_name, derefed_dynamic_type_size)
233 if offset < derefed_dynamic_type_size:
234 member_list = list();
235 get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
236 if member_list:
237 member_path = ''
238 for member in member_list:
239 member_name = member.name
240 if member_name:
241 if member_path:
242 member_path += '.'
243 member_path += member_name
244 if member_path:
245 if options.ivar_regex_blacklist:
246 for ivar_regex in options.ivar_regex_blacklist:
247 if ivar_regex.match(member_path):
248 print_entry = False
249 description += ', ivar = %s' % (member_path)
Greg Claytone04cfd22012-07-11 22:13:18 +0000250 if print_entry:
Greg Clayton774ebdf2012-08-11 02:26:26 +0000251 match_idx += 1
Greg Claytone04cfd22012-07-11 22:13:18 +0000252 if description:
Greg Claytonc373ca52012-09-01 00:34:35 +0000253 result.AppendMessage(description)
Greg Claytone04cfd22012-07-11 22:13:18 +0000254 if options.print_type and derefed_dynamic_value:
Greg Claytonc373ca52012-09-01 00:34:35 +0000255 result.AppendMessage('%s' % (derefed_dynamic_value))
Greg Claytone04cfd22012-07-11 22:13:18 +0000256 if options.print_object_description and dynamic_value:
257 desc = dynamic_value.GetObjectDescription()
258 if desc:
Greg Claytonc373ca52012-09-01 00:34:35 +0000259 result.AppendMessage(', po=%s' % (desc))
Greg Claytone04cfd22012-07-11 22:13:18 +0000260 if options.memory:
261 cmd_result = lldb.SBCommandReturnObject()
262 memory_command = "memory read -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
263 lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
Greg Claytonc373ca52012-09-01 00:34:35 +0000264 result.AppendMessage(cmd_result.GetOutput())
Greg Claytone04cfd22012-07-11 22:13:18 +0000265 if options.stack_history:
Greg Claytonc373ca52012-09-01 00:34:35 +0000266 dump_stack_history_entries(result, malloc_addr, 1)
Greg Claytone04cfd22012-07-11 22:13:18 +0000267 elif options.stack:
Greg Claytonc373ca52012-09-01 00:34:35 +0000268 dump_stack_history_entries(result, malloc_addr, 0)
Greg Claytone04cfd22012-07-11 22:13:18 +0000269 return i
270 elif print_no_matches:
Greg Claytonc373ca52012-09-01 00:34:35 +0000271 result.AppendMessage('no matches found for %s' % (arg_str_description))
Greg Clayton7fb671b2012-04-11 18:30:53 +0000272 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000273 result.AppendMessage(expr_sbvalue.error )
Greg Claytone04cfd22012-07-11 22:13:18 +0000274 return 0
275
Greg Claytonc373ca52012-09-01 00:34:35 +0000276def heap_search(result, options, arg_str):
Greg Claytone04cfd22012-07-11 22:13:18 +0000277 dylid_load_err = load_dylib()
278 if dylid_load_err:
Greg Claytonc373ca52012-09-01 00:34:35 +0000279 result.AppendMessage(dylid_load_err)
Greg Claytone04cfd22012-07-11 22:13:18 +0000280 return
281 expr = None
282 arg_str_description = arg_str
Greg Claytone04cfd22012-07-11 22:13:18 +0000283 if options.type == 'pointer':
284 expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
285 arg_str_description = 'malloc block containing pointer %s' % arg_str
286 if options.format == None:
287 options.format = "A" # 'A' is "address" format
Greg Clayton774ebdf2012-08-11 02:26:26 +0000288 elif options.type == 'isa':
289 expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
290 arg_str_description = 'objective C classes with isa %s' % arg_str
291 options.offset = 0
292 if options.format == None:
293 options.format = "A" # 'A' is "address" format
Greg Claytone04cfd22012-07-11 22:13:18 +0000294 elif options.type == 'cstr':
295 expr = 'find_cstring_in_heap("%s")' % arg_str
296 arg_str_description = 'malloc block containing "%s"' % arg_str
297 elif options.type == 'addr':
298 expr = 'find_block_for_address((void *)%s)' % arg_str
299 arg_str_description = 'malloc block for %s' % arg_str
300 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000301 result.AppendMessage('error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type)
Greg Claytone04cfd22012-07-11 22:13:18 +0000302 return
Greg Claytonc373ca52012-09-01 00:34:35 +0000303 if options.format == None:
304 options.format = "Y" # 'Y' is "bytes with ASCII" format
Greg Claytone04cfd22012-07-11 22:13:18 +0000305
Greg Claytonc373ca52012-09-01 00:34:35 +0000306 display_match_results (result, options, arg_str_description, lldb.frame.EvaluateExpression (expr))
Greg Clayton7fb671b2012-04-11 18:30:53 +0000307
Greg Clayton77677162012-04-12 18:57:36 +0000308def ptr_refs(debugger, command, result, dict):
Greg Clayton804de012012-04-11 16:27:06 +0000309 command_args = shlex.split(command)
Greg Clayton341039f2012-05-11 02:42:36 +0000310 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
Greg Clayton7fb671b2012-04-11 18:30:53 +0000311 description='''Searches the heap for pointer references on darwin user space programs.
312
313 Any matches that were found will dump the malloc blocks that contain the pointers
314 and might be able to print what kind of objects the pointers are contained in using
Greg Clayton77677162012-04-12 18:57:36 +0000315 dynamic type information in the program.'''
316 parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
Greg Claytond84bb482012-04-13 16:24:09 +0000317 add_common_options(parser)
Greg Clayton804de012012-04-11 16:27:06 +0000318 try:
319 (options, args) = parser.parse_args(command_args)
320 except:
321 return
Greg Clayton7fb671b2012-04-11 18:30:53 +0000322
323 options.type = 'pointer'
Greg Clayton804de012012-04-11 16:27:06 +0000324
325 if args:
326
327 for data in args:
Greg Claytonc373ca52012-09-01 00:34:35 +0000328 heap_search (result, options, data)
Greg Clayton804de012012-04-11 16:27:06 +0000329 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000330 resultresult.AppendMessage('error: no pointer arguments were given')
Greg Clayton804de012012-04-11 16:27:06 +0000331
Greg Clayton77677162012-04-12 18:57:36 +0000332def cstr_refs(debugger, command, result, dict):
Greg Clayton7fb671b2012-04-11 18:30:53 +0000333 command_args = shlex.split(command)
Greg Clayton77677162012-04-12 18:57:36 +0000334 usage = "usage: %prog [options] <CSTR> [CSTR ...]"
Greg Clayton7fb671b2012-04-11 18:30:53 +0000335 description='''Searches the heap for C string references on darwin user space programs.
336
337 Any matches that were found will dump the malloc blocks that contain the C strings
338 and might be able to print what kind of objects the pointers are contained in using
Greg Clayton77677162012-04-12 18:57:36 +0000339 dynamic type information in the program.'''
340 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Claytond84bb482012-04-13 16:24:09 +0000341 add_common_options(parser)
Greg Clayton7fb671b2012-04-11 18:30:53 +0000342 try:
343 (options, args) = parser.parse_args(command_args)
344 except:
345 return
346
347 options.type = 'cstr'
348
349 if args:
350
351 for data in args:
Greg Claytonc373ca52012-09-01 00:34:35 +0000352 heap_search (result, options, data)
Greg Clayton7fb671b2012-04-11 18:30:53 +0000353 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000354 result.AppendMessage('error: no c string arguments were given to search for');
Greg Clayton804de012012-04-11 16:27:06 +0000355
Greg Clayton77677162012-04-12 18:57:36 +0000356def malloc_info(debugger, command, result, dict):
357 command_args = shlex.split(command)
Greg Clayton341039f2012-05-11 02:42:36 +0000358 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
Greg Clayton77677162012-04-12 18:57:36 +0000359 description='''Searches the heap a malloc block that contains the addresses specified as arguments.
360
361 Any matches that were found will dump the malloc blocks that match or contain
362 the specified address. The matching blocks might be able to show what kind
363 of objects they are using dynamic type information in the program.'''
364 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Claytond84bb482012-04-13 16:24:09 +0000365 add_common_options(parser)
Greg Clayton77677162012-04-12 18:57:36 +0000366 try:
367 (options, args) = parser.parse_args(command_args)
368 except:
369 return
Greg Clayton77677162012-04-12 18:57:36 +0000370 options.type = 'addr'
Greg Clayton77677162012-04-12 18:57:36 +0000371 if args:
Greg Clayton77677162012-04-12 18:57:36 +0000372 for data in args:
Greg Claytonc373ca52012-09-01 00:34:35 +0000373 heap_search (result, options, data)
Greg Clayton77677162012-04-12 18:57:36 +0000374 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000375 result.AppendMessage('error: no c string arguments were given to search for')
Greg Clayton77677162012-04-12 18:57:36 +0000376
Greg Clayton341039f2012-05-11 02:42:36 +0000377def malloc_history(debugger, command, result, dict):
378 command_args = shlex.split(command)
379 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
380 description='''Gets the allocation history for an expression whose result is an address.
381
Greg Claytonc373ca52012-09-01 00:34:35 +0000382 Programs should set the MallocStackLogging=1 in the environment to enable stack history. This can be done
383 with "process launch -v MallocStackLogging=1 -- [arg1 ...]"'''
Greg Clayton341039f2012-05-11 02:42:36 +0000384
385 dylid_load_err = load_dylib()
386 if dylid_load_err:
Greg Claytonc373ca52012-09-01 00:34:35 +0000387 result.AppendMessage(dylid_load_err)
Greg Clayton341039f2012-05-11 02:42:36 +0000388 else:
389 if command_args:
390 for addr_expr_str in command_args:
391 expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
392 if expr_sbvalue.error.Success():
393 addr = expr_sbvalue.unsigned
394 if addr != 0:
395 dump_stack_history_entries (addr, 1)
396 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000397 result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error))
Greg Clayton341039f2012-05-11 02:42:36 +0000398 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000399 result.AppendMessage('error: no address expressions were specified')
Greg Clayton341039f2012-05-11 02:42:36 +0000400
Greg Claytone04cfd22012-07-11 22:13:18 +0000401def section_ptr_refs(debugger, command, result, dict):
402 command_args = shlex.split(command)
403 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
404 description='''Searches section contents for pointer values in darwin user space programs.'''
405 parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage)
406 add_common_options(parser)
407 parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list())
408 try:
409 (options, args) = parser.parse_args(command_args)
410 except:
411 return
412
413 options.type = 'pointer'
414
415 sections = list()
416 section_modules = list()
417 if not options.section_names:
Greg Claytonc373ca52012-09-01 00:34:35 +0000418 result.AppendMessage('error: at least one section must be specified with the --section option')
Greg Claytone04cfd22012-07-11 22:13:18 +0000419 return
420
421 for module in lldb.target.modules:
422 for section_name in options.section_names:
423 section = module.section[section_name]
424 if section:
425 sections.append (section)
426 section_modules.append (module)
427 if sections:
428 dylid_load_err = load_dylib()
429 if dylid_load_err:
Greg Claytonc373ca52012-09-01 00:34:35 +0000430 result.AppendMessage(dylid_load_err)
Greg Claytone04cfd22012-07-11 22:13:18 +0000431 return
432 for expr_str in args:
433 for (idx, section) in enumerate(sections):
434 expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str)
435 arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str)
Greg Claytonc373ca52012-09-01 00:34:35 +0000436 num_matches = display_match_results (result, options, arg_str_description, lldb.frame.EvaluateExpression (expr), False)
Greg Claytone04cfd22012-07-11 22:13:18 +0000437 if num_matches:
438 if num_matches < options.max_matches:
439 options.max_matches = options.max_matches - num_matches
440 else:
441 options.max_matches = 0
442 if options.max_matches == 0:
443 return
444 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000445 result.AppendMessage('error: no sections were found that match any of %s' % (', '.join(options.section_names)))
Greg Claytone04cfd22012-07-11 22:13:18 +0000446
Greg Clayton774ebdf2012-08-11 02:26:26 +0000447def objc_refs(debugger, command, result, dict):
448 command_args = shlex.split(command)
449 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
450 description='''Find all heap allocations given one or more objective C class names.'''
451 parser = optparse.OptionParser(description=description, prog='object_refs',usage=usage)
452 add_common_options(parser)
453 try:
454 (options, args) = parser.parse_args(command_args)
455 except:
456 return
457
458 dylid_load_err = load_dylib()
459 if dylid_load_err:
Greg Claytonc373ca52012-09-01 00:34:35 +0000460 result.AppendMessage(dylid_load_err)
Greg Clayton774ebdf2012-08-11 02:26:26 +0000461 else:
462 if args:
463 for class_name in args:
464 addr_expr_str = "(void *)[%s class]" % class_name
465 expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
466 if expr_sbvalue.error.Success():
467 isa = expr_sbvalue.unsigned
468 if isa:
469 options.type = 'isa'
Greg Claytonc373ca52012-09-01 00:34:35 +0000470 heap_search (result, options, '0x%x' % isa)
Greg Clayton774ebdf2012-08-11 02:26:26 +0000471 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000472 result.AppendMessage('error: Can\'t find isa for an ObjC class named "%s"' % (class_name))
Greg Clayton774ebdf2012-08-11 02:26:26 +0000473 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000474 result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error))
Greg Clayton774ebdf2012-08-11 02:26:26 +0000475 else:
Greg Claytonc373ca52012-09-01 00:34:35 +0000476 result.AppendMessage('error: no address expressions were specified')
Greg Clayton774ebdf2012-08-11 02:26:26 +0000477
Greg Claytond712ef02012-04-25 18:40:20 +0000478if __name__ == '__main__':
479 lldb.debugger = lldb.SBDebugger.Create()
480
481# This initializer is being run from LLDB in the embedded command interpreter
482# Add any commands contained in this module to LLDB
483lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.ptr_refs ptr_refs')
484lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs')
485lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info')
Greg Clayton341039f2012-05-11 02:42:36 +0000486lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_history malloc_history')
Greg Claytone04cfd22012-07-11 22:13:18 +0000487lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_refs')
Greg Clayton774ebdf2012-08-11 02:26:26 +0000488lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.objc_refs objc_refs')
Greg Claytone04cfd22012-07-11 22:13:18 +0000489print '"ptr_refs", "cstr_refs", "malloc_info", "malloc_history" and "section_ptr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
Greg Clayton804de012012-04-11 16:27:06 +0000490
491
492
493