blob: ea023f25e9e40ebfb2eaa996b6950af3bbd92a7d [file] [log] [blame]
Greg Claytone93e24f2012-04-11 16:27:06 +00001#!/usr/bin/python
2
3#----------------------------------------------------------------------
Greg Clayton1dae6f32012-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 Claytone93e24f2012-04-11 16:27:06 +00007#
Greg Clayton1dae6f32012-04-25 18:40:20 +00008# (lldb) script import lldb.macosx.heap
Greg Claytone93e24f2012-04-11 16:27:06 +00009#----------------------------------------------------------------------
10
11import lldb
12import commands
13import optparse
Greg Clayton96666442012-04-11 18:30:53 +000014import os
Greg Clayton1dae6f32012-04-25 18:40:20 +000015import os.path
Greg Clayton4c5c4292012-07-11 22:13:18 +000016import re
Greg Claytone93e24f2012-04-11 16:27:06 +000017import shlex
Greg Clayton1dae6f32012-04-25 18:40:20 +000018import string
19import tempfile
Greg Clayton6f2f0ab2012-04-25 01:49:50 +000020import lldb.utils.symbolication
Greg Claytone93e24f2012-04-11 16:27:06 +000021
Greg Clayton1dae6f32012-04-25 18:40:20 +000022g_libheap_dylib_dir = None
23g_libheap_dylib_dict = dict()
Greg Claytonbf479652012-05-11 02:42:36 +000024g_verbose = False
Greg Clayton1dae6f32012-04-25 18:40:20 +000025
Greg Clayton9098fee2012-04-21 00:11:26 +000026def load_dylib():
27 if lldb.target:
Greg Clayton1dae6f32012-04-25 18:40:20 +000028 global g_libheap_dylib_dir
29 global g_libheap_dylib_dict
30 triple = lldb.target.triple
Greg Clayton3e339792012-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 Clayton1dae6f32012-04-25 18:40:20 +000034 if not g_libheap_dylib_dir:
Greg Clayton3e339792012-04-25 21:23:07 +000035 g_libheap_dylib_dir = tempfile.gettempdir() + '/lldb-dylibs'
36 triple_dir = g_libheap_dylib_dir + '/' + triple + '/' + __name__
Greg Clayton1dae6f32012-04-25 18:40:20 +000037 if not os.path.exists(triple_dir):
Greg Clayton3e339792012-04-25 21:23:07 +000038 os.makedirs(triple_dir)
Greg Clayton1dae6f32012-04-25 18:40:20 +000039 libheap_dylib_path = triple_dir + '/libheap.dylib'
40 g_libheap_dylib_dict[triple] = libheap_dylib_path
Greg Clayton3e339792012-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 Clayton1dae6f32012-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 Clayton3e339792012-04-25 21:23:07 +000047 # print make_command
Greg Clayton0cae0632012-06-27 19:57:59 +000048 (make_exit_status, make_output) = commands.getstatusoutput(make_command)
49 if make_exit_status != 0:
50 print make_output
Greg Clayton9098fee2012-04-21 00:11:26 +000051 if os.path.exists(libheap_dylib_path):
52 libheap_dylib_spec = lldb.SBFileSpec(libheap_dylib_path)
53 if lldb.target.FindModule(libheap_dylib_spec):
54 return None # success, 'libheap.dylib' already loaded
55 if lldb.process:
56 state = lldb.process.state
57 if state == lldb.eStateStopped:
58 (libheap_dylib_path)
59 error = lldb.SBError()
60 image_idx = lldb.process.LoadImage(libheap_dylib_spec, error)
61 if error.Success():
62 return None
63 else:
64 if error:
65 return 'error: %s' % error
66 else:
67 return 'error: "process load \'%s\'" failed' % libheap_dylib_spec
68 else:
69 return 'error: process is not stopped'
70 else:
71 return 'error: invalid process'
72 else:
73 return 'error: file does not exist "%s"' % libheap_dylib_path
74 else:
75 return 'error: invalid target'
76
77 debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
Greg Claytonbf479652012-05-11 02:42:36 +000078 if lldb.target.FindModule(libheap_dylib_spec):
79 return None # success, 'libheap.dylib' already loaded
80 return 'error: failed to load "%s"' % libheap_dylib_path
Greg Clayton0d0f56d2012-07-07 01:22:45 +000081
82def get_member_types_for_offset(value_type, offset, member_list):
83 member = value_type.GetFieldAtIndex(0)
84 search_bases = False
85 if member:
86 if member.GetOffsetInBytes() <= offset:
87 for field_idx in range (value_type.GetNumberOfFields()):
88 member = value_type.GetFieldAtIndex(field_idx)
89 member_byte_offset = member.GetOffsetInBytes()
90 member_end_byte_offset = member_byte_offset + member.type.size
91 if member_byte_offset <= offset and offset < member_end_byte_offset:
92 member_list.append(member)
93 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
94 return
95 else:
96 search_bases = True
97 else:
98 search_bases = True
99 if search_bases:
100 for field_idx in range (value_type.GetNumberOfDirectBaseClasses()):
101 member = value_type.GetDirectBaseClassAtIndex(field_idx)
102 member_byte_offset = member.GetOffsetInBytes()
103 member_end_byte_offset = member_byte_offset + member.type.size
104 if member_byte_offset <= offset and offset < member_end_byte_offset:
105 member_list.append(member)
106 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
107 return
108 for field_idx in range (value_type.GetNumberOfVirtualBaseClasses()):
109 member = value_type.GetVirtualBaseClassAtIndex(field_idx)
110 member_byte_offset = member.GetOffsetInBytes()
111 member_end_byte_offset = member_byte_offset + member.type.size
112 if member_byte_offset <= offset and offset < member_end_byte_offset:
113 member_list.append(member)
114 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
115 return
Greg Clayton4c5c4292012-07-11 22:13:18 +0000116
117def append_regex_callback(option, opt, value, parser):
118 try:
119 ivar_regex = re.compile(value)
120 parser.values.ivar_regex_blacklist.append(ivar_regex)
121 except:
122 print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
Greg Clayton9098fee2012-04-21 00:11:26 +0000123
Greg Clayton93e5ba52012-04-13 16:24:09 +0000124def add_common_options(parser):
125 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
Greg Clayton4c5c4292012-07-11 22:13:18 +0000126 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 Clayton93e5ba52012-04-13 16:24:09 +0000127 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
128 parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
129 parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
Greg Clayton4c5c4292012-07-11 22:13:18 +0000130 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 Clayton9098fee2012-04-21 00:11:26 +0000131 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 Clayton7a245762012-05-10 23:17:28 +0000132 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 Clayton4c5c4292012-07-11 22:13:18 +0000133 parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=256)
Greg Claytonab20f292012-08-11 02:26:26 +0000134 parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1)
Greg Clayton7a245762012-05-10 23:17:28 +0000135
Greg Clayton7a245762012-05-10 23:17:28 +0000136def dump_stack_history_entry(stack_history_entry, idx):
Greg Clayton6f446f32012-05-10 23:37:52 +0000137 address = int(stack_history_entry.address)
138 if address:
139 type_flags = int(stack_history_entry.type_flags)
Greg Clayton7a245762012-05-10 23:17:28 +0000140 symbolicator = lldb.utils.symbolication.Symbolicator()
141 symbolicator.target = lldb.target
Greg Claytonbf479652012-05-11 02:42:36 +0000142 type_str = ''
143 if type_flags == 0:
144 type_str = 'free'
145 else:
146 if type_flags & 2:
147 type_str = 'alloc'
148 elif type_flags & 4:
149 type_str = 'free'
150 elif type_flags & 1:
151 type_str = 'generic'
152 else:
153 type_str = hex(type_flags)
154 print 'stack[%u]: addr = 0x%x, type=%s, frames:' % (idx, address, type_str)
Greg Clayton7a245762012-05-10 23:17:28 +0000155 frame_idx = 0
Greg Clayton6f446f32012-05-10 23:37:52 +0000156 idx = 0
157 pc = int(stack_history_entry.frames[idx])
Greg Clayton7a245762012-05-10 23:17:28 +0000158 while pc != 0:
159 if pc >= 0x1000:
160 frames = symbolicator.symbolicate(pc)
161 if frames:
162 for frame in frames:
Greg Claytonbf479652012-05-11 02:42:36 +0000163 print ' [%u] %s' % (frame_idx, frame)
Greg Clayton7a245762012-05-10 23:17:28 +0000164 frame_idx += 1
165 else:
Greg Claytonbf479652012-05-11 02:42:36 +0000166 print ' [%u] 0x%x' % (frame_idx, pc)
Greg Clayton7a245762012-05-10 23:17:28 +0000167 frame_idx += 1
Greg Clayton6f446f32012-05-10 23:37:52 +0000168 idx = idx + 1
169 pc = int(stack_history_entry.frames[idx])
Greg Clayton7a245762012-05-10 23:17:28 +0000170 else:
171 pc = 0
Greg Claytonbf479652012-05-11 02:42:36 +0000172 print
Greg Clayton7a245762012-05-10 23:17:28 +0000173
Greg Claytonbf479652012-05-11 02:42:36 +0000174def dump_stack_history_entries(addr, history):
Greg Clayton7a245762012-05-10 23:17:28 +0000175 # malloc_stack_entry *get_stack_history_for_address (const void * addr)
Greg Claytonbf479652012-05-11 02:42:36 +0000176 expr = 'get_stack_history_for_address((void *)0x%x, %u)' % (addr, history)
Greg Clayton7a245762012-05-10 23:17:28 +0000177 expr_sbvalue = lldb.frame.EvaluateExpression (expr)
178 if expr_sbvalue.error.Success():
179 if expr_sbvalue.unsigned:
180 expr_value = lldb.value(expr_sbvalue)
181 idx = 0;
182 stack_history_entry = expr_value[idx]
Greg Clayton6f446f32012-05-10 23:37:52 +0000183 while int(stack_history_entry.address) != 0:
Greg Clayton7a245762012-05-10 23:17:28 +0000184 dump_stack_history_entry(stack_history_entry, idx)
185 idx = idx + 1
186 stack_history_entry = expr_value[idx]
Greg Claytonbf479652012-05-11 02:42:36 +0000187 else:
188 print 'error: expression failed "%s" => %s' % (expr, expr_sbvalue.error)
Greg Clayton7a245762012-05-10 23:17:28 +0000189
Greg Clayton4c5c4292012-07-11 22:13:18 +0000190
191def display_match_results (options, arg_str_description, expr_sbvalue, print_no_matches = True):
Greg Clayton96666442012-04-11 18:30:53 +0000192 if expr_sbvalue.error.Success():
193 if expr_sbvalue.unsigned:
194 match_value = lldb.value(expr_sbvalue)
195 i = 0
Greg Claytonab20f292012-08-11 02:26:26 +0000196 match_idx = 0
Greg Clayton96666442012-04-11 18:30:53 +0000197 while 1:
Greg Clayton4c5c4292012-07-11 22:13:18 +0000198 print_entry = True
Greg Clayton96666442012-04-11 18:30:53 +0000199 match_entry = match_value[i]; i += 1
Greg Clayton4c5c4292012-07-11 22:13:18 +0000200 if i >= options.max_matches:
201 print 'error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)
202 break
Greg Clayton96666442012-04-11 18:30:53 +0000203 malloc_addr = match_entry.addr.sbvalue.unsigned
204 if malloc_addr == 0:
205 break
206 malloc_size = int(match_entry.size)
207 offset = int(match_entry.offset)
Greg Claytonab20f292012-08-11 02:26:26 +0000208
209 if options.offset >= 0 and options.offset != offset:
210 print_entry = False
211 else:
212 match_addr = malloc_addr + offset
213 dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
214 description = '[%u] %s: addr = 0x%x' % (match_idx, arg_str_description, malloc_addr)
215 if offset != 0:
216 description += ' + %u' % (offset)
217 description += ', size = %u' % (malloc_size)
218 derefed_dynamic_value = None
219 if dynamic_value.type.name == 'void *':
220 if options.type == 'pointer' and malloc_size == 4096:
221 error = lldb.SBError()
222 data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
223 if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
224 description += ', type = (AUTORELEASE!)'
225 else:
226 derefed_dynamic_value = dynamic_value.deref
227 if derefed_dynamic_value:
228 derefed_dynamic_type = derefed_dynamic_value.type
229 derefed_dynamic_type_size = derefed_dynamic_type.size
230 derefed_dynamic_type_name = derefed_dynamic_type.name
231 description += ', type = %s <%u>' % (derefed_dynamic_type_name, derefed_dynamic_type_size)
232 if offset < derefed_dynamic_type_size:
233 member_list = list();
234 get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
235 if member_list:
236 member_path = ''
237 for member in member_list:
238 member_name = member.name
239 if member_name:
240 if member_path:
241 member_path += '.'
242 member_path += member_name
243 if member_path:
244 if options.ivar_regex_blacklist:
245 for ivar_regex in options.ivar_regex_blacklist:
246 if ivar_regex.match(member_path):
247 print_entry = False
248 description += ', ivar = %s' % (member_path)
Greg Clayton4c5c4292012-07-11 22:13:18 +0000249 if print_entry:
Greg Claytonab20f292012-08-11 02:26:26 +0000250 match_idx += 1
Greg Clayton4c5c4292012-07-11 22:13:18 +0000251 if description:
252 print description
253 if options.print_type and derefed_dynamic_value:
254 print derefed_dynamic_value
255 if options.print_object_description and dynamic_value:
256 desc = dynamic_value.GetObjectDescription()
257 if desc:
Greg Claytonab20f292012-08-11 02:26:26 +0000258 print ', po=%s\n' % (desc)
Greg Clayton4c5c4292012-07-11 22:13:18 +0000259 if options.memory:
260 cmd_result = lldb.SBCommandReturnObject()
261 memory_command = "memory read -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
262 lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
263 print cmd_result.GetOutput()
264 if options.stack_history:
265 dump_stack_history_entries(malloc_addr, 1)
266 elif options.stack:
267 dump_stack_history_entries(malloc_addr, 0)
268 return i
269 elif print_no_matches:
270 print 'no matches found for %s' % (arg_str_description)
Greg Clayton96666442012-04-11 18:30:53 +0000271 else:
Greg Claytonbff78412012-04-12 18:57:36 +0000272 print expr_sbvalue.error
Greg Clayton4c5c4292012-07-11 22:13:18 +0000273 return 0
274
275def heap_search(options, arg_str):
276 dylid_load_err = load_dylib()
277 if dylid_load_err:
278 print dylid_load_err
279 return
280 expr = None
281 arg_str_description = arg_str
282 if options.format == None:
283 options.format = "Y" # 'Y' is "bytes with ASCII" format
284 if options.type == 'pointer':
285 expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
286 arg_str_description = 'malloc block containing pointer %s' % arg_str
287 if options.format == None:
288 options.format = "A" # 'A' is "address" format
Greg Claytonab20f292012-08-11 02:26:26 +0000289 elif options.type == 'isa':
290 expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
291 arg_str_description = 'objective C classes with isa %s' % arg_str
292 options.offset = 0
293 if options.format == None:
294 options.format = "A" # 'A' is "address" format
Greg Clayton4c5c4292012-07-11 22:13:18 +0000295 elif options.type == 'cstr':
296 expr = 'find_cstring_in_heap("%s")' % arg_str
297 arg_str_description = 'malloc block containing "%s"' % arg_str
298 elif options.type == 'addr':
299 expr = 'find_block_for_address((void *)%s)' % arg_str
300 arg_str_description = 'malloc block for %s' % arg_str
301 else:
302 print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
303 return
304
305 display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr))
Greg Clayton96666442012-04-11 18:30:53 +0000306
Greg Claytonbff78412012-04-12 18:57:36 +0000307def ptr_refs(debugger, command, result, dict):
Greg Claytone93e24f2012-04-11 16:27:06 +0000308 command_args = shlex.split(command)
Greg Claytonbf479652012-05-11 02:42:36 +0000309 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000310 description='''Searches the heap for pointer references on darwin user space programs.
311
312 Any matches that were found will dump the malloc blocks that contain the pointers
313 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000314 dynamic type information in the program.'''
315 parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000316 add_common_options(parser)
Greg Claytone93e24f2012-04-11 16:27:06 +0000317 try:
318 (options, args) = parser.parse_args(command_args)
319 except:
320 return
Greg Clayton96666442012-04-11 18:30:53 +0000321
322 options.type = 'pointer'
Greg Claytone93e24f2012-04-11 16:27:06 +0000323
324 if args:
325
326 for data in args:
Greg Clayton96666442012-04-11 18:30:53 +0000327 heap_search (options, data)
Greg Claytone93e24f2012-04-11 16:27:06 +0000328 else:
Greg Clayton96666442012-04-11 18:30:53 +0000329 print 'error: no pointer arguments were given'
Greg Claytone93e24f2012-04-11 16:27:06 +0000330
Greg Claytonbff78412012-04-12 18:57:36 +0000331def cstr_refs(debugger, command, result, dict):
Greg Clayton96666442012-04-11 18:30:53 +0000332 command_args = shlex.split(command)
Greg Claytonbff78412012-04-12 18:57:36 +0000333 usage = "usage: %prog [options] <CSTR> [CSTR ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000334 description='''Searches the heap for C string references on darwin user space programs.
335
336 Any matches that were found will dump the malloc blocks that contain the C strings
337 and might be able to print what kind of objects the pointers are contained in using
Greg Claytonbff78412012-04-12 18:57:36 +0000338 dynamic type information in the program.'''
339 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000340 add_common_options(parser)
Greg Clayton96666442012-04-11 18:30:53 +0000341 try:
342 (options, args) = parser.parse_args(command_args)
343 except:
344 return
345
346 options.type = 'cstr'
347
348 if args:
349
350 for data in args:
351 heap_search (options, data)
352 else:
353 print 'error: no c string arguments were given to search for'
Greg Claytone93e24f2012-04-11 16:27:06 +0000354
Greg Claytonbff78412012-04-12 18:57:36 +0000355def malloc_info(debugger, command, result, dict):
356 command_args = shlex.split(command)
Greg Claytonbf479652012-05-11 02:42:36 +0000357 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
Greg Claytonbff78412012-04-12 18:57:36 +0000358 description='''Searches the heap a malloc block that contains the addresses specified as arguments.
359
360 Any matches that were found will dump the malloc blocks that match or contain
361 the specified address. The matching blocks might be able to show what kind
362 of objects they are using dynamic type information in the program.'''
363 parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
Greg Clayton93e5ba52012-04-13 16:24:09 +0000364 add_common_options(parser)
Greg Claytonbff78412012-04-12 18:57:36 +0000365 try:
366 (options, args) = parser.parse_args(command_args)
367 except:
368 return
Greg Claytonbff78412012-04-12 18:57:36 +0000369 options.type = 'addr'
Greg Claytonbff78412012-04-12 18:57:36 +0000370 if args:
Greg Claytonbff78412012-04-12 18:57:36 +0000371 for data in args:
372 heap_search (options, data)
373 else:
374 print 'error: no c string arguments were given to search for'
375
Greg Claytonbf479652012-05-11 02:42:36 +0000376def malloc_history(debugger, command, result, dict):
377 command_args = shlex.split(command)
378 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
379 description='''Gets the allocation history for an expression whose result is an address.
380
381 Programs should set the MallocStackLoggingNoCompact=1 in the environment to enable stack history. This can be done
382 with "process launch -v MallocStackLoggingNoCompact=1 -- [arg1 ...]"'''
383
384 dylid_load_err = load_dylib()
385 if dylid_load_err:
386 print dylid_load_err
387 else:
388 if command_args:
389 for addr_expr_str in command_args:
390 expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
391 if expr_sbvalue.error.Success():
392 addr = expr_sbvalue.unsigned
393 if addr != 0:
394 dump_stack_history_entries (addr, 1)
395 else:
396 print 'error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error)
397 else:
398 print 'error: no address expressions were specified'
399
Greg Clayton4c5c4292012-07-11 22:13:18 +0000400def section_ptr_refs(debugger, command, result, dict):
401 command_args = shlex.split(command)
402 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
403 description='''Searches section contents for pointer values in darwin user space programs.'''
404 parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage)
405 add_common_options(parser)
406 parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list())
407 try:
408 (options, args) = parser.parse_args(command_args)
409 except:
410 return
411
412 options.type = 'pointer'
413
414 sections = list()
415 section_modules = list()
416 if not options.section_names:
417 print 'error: at least one section must be specified with the --section option'
418 return
419
420 for module in lldb.target.modules:
421 for section_name in options.section_names:
422 section = module.section[section_name]
423 if section:
424 sections.append (section)
425 section_modules.append (module)
426 if sections:
427 dylid_load_err = load_dylib()
428 if dylid_load_err:
429 print dylid_load_err
430 return
431 for expr_str in args:
432 for (idx, section) in enumerate(sections):
433 expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str)
434 arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str)
435 num_matches = display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr), False)
436 if num_matches:
437 if num_matches < options.max_matches:
438 options.max_matches = options.max_matches - num_matches
439 else:
440 options.max_matches = 0
441 if options.max_matches == 0:
442 return
443 else:
444 print 'error: no sections were found that match any of %s' % (', '.join(options.section_names))
445
Greg Claytonab20f292012-08-11 02:26:26 +0000446def objc_refs(debugger, command, result, dict):
447 command_args = shlex.split(command)
448 usage = "usage: %prog [options] <EXPR> [EXPR ...]"
449 description='''Find all heap allocations given one or more objective C class names.'''
450 parser = optparse.OptionParser(description=description, prog='object_refs',usage=usage)
451 add_common_options(parser)
452 try:
453 (options, args) = parser.parse_args(command_args)
454 except:
455 return
456
457 dylid_load_err = load_dylib()
458 if dylid_load_err:
459 print dylid_load_err
460 else:
461 if args:
462 for class_name in args:
463 addr_expr_str = "(void *)[%s class]" % class_name
464 expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
465 if expr_sbvalue.error.Success():
466 isa = expr_sbvalue.unsigned
467 if isa:
468 options.type = 'isa'
469 heap_search (options, '0x%x' % isa)
470 else:
471 print 'error: Can\'t find isa for an ObjC class named "%s"' % (class_name)
472 else:
473 print 'error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error)
474 else:
475 print 'error: no address expressions were specified'
476
Greg Clayton1dae6f32012-04-25 18:40:20 +0000477if __name__ == '__main__':
478 lldb.debugger = lldb.SBDebugger.Create()
479
480# This initializer is being run from LLDB in the embedded command interpreter
481# Add any commands contained in this module to LLDB
482lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.ptr_refs ptr_refs')
483lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs')
484lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info')
Greg Claytonbf479652012-05-11 02:42:36 +0000485lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_history malloc_history')
Greg Clayton4c5c4292012-07-11 22:13:18 +0000486lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_refs')
Greg Claytonab20f292012-08-11 02:26:26 +0000487lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.objc_refs objc_refs')
Greg Clayton4c5c4292012-07-11 22:13:18 +0000488print '"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 Claytone93e24f2012-04-11 16:27:06 +0000489
490
491
492