blob: bb2a63961ab02980cf90f2e1e351c9adfefa2ffd [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
26 if options.type == 'pointer':
27 ptr = int(arg_str, 0)
28 expr = 'find_pointer_in_heap(0x%x)' % ptr
29 elif options.type == 'cstr':
30 expr = 'find_cstring_in_heap("%s")' % arg_str
31 else:
32 print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
33 return
34
35 expr_sbvalue = lldb.frame.EvaluateExpression (expr)
36 if expr_sbvalue.error.Success():
37 if expr_sbvalue.unsigned:
38 match_value = lldb.value(expr_sbvalue)
39 i = 0
40 while 1:
41 match_entry = match_value[i]; i += 1
42 malloc_addr = match_entry.addr.sbvalue.unsigned
43 if malloc_addr == 0:
44 break
45 malloc_size = int(match_entry.size)
46 offset = int(match_entry.offset)
47 dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
48 # If the type is still 'void *' then we weren't able to figure
49 # out a dynamic type for the malloc_addr
50 type_name = dynamic_value.type.name
51 if type_name == 'void *':
52 if options.type == 'pointer' and malloc_size == 4096:
53 error = lldb.SBError()
54 data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
55 if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
56 print 'found %s %s: block = 0x%x, size = %u, offset = %u, type = (autorelease object pool)' % (options.type, arg_str, malloc_addr, malloc_size, offset)
57 continue
58
59 print 'found %s %s: block = 0x%x, size = %u, offset = %u, type = \'%s\'' % (options.type, arg_str, malloc_addr, malloc_size, offset, type_name),
60 derefed_dynamic_value = dynamic_value.deref
61 ivar_member = None
62 if derefed_dynamic_value:
63 derefed_dynamic_type = derefed_dynamic_value.type
64 member = derefed_dynamic_type.GetFieldAtIndex(0)
65 search_bases = False
66 if member:
67 if member.GetOffsetInBytes() <= offset:
68 for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
69 member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
70 member_byte_offset = member.GetOffsetInBytes()
71 if member_byte_offset == offset:
72 ivar_member = member
73 break
74 else:
75 search_bases = True
76 else:
77 search_bases = True
78
79 if not ivar_member and search_bases:
80 for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
81 member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
82 member_byte_offset = member.GetOffsetInBytes()
83 if member_byte_offset == offset:
84 ivar_member = member
85 break
86 if not ivar_member:
87 for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
88 member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
89 member_byte_offset = member.GetOffsetInBytes()
90 if member_byte_offset == offset:
91 ivar_member = member
92 break
93 if ivar_member:
94 print ", ivar = %s" % ivar_member.name,
95 print "\n", dynamic_value.deref
96 else:
97 print
98 if options.print_object_description:
99 desc = dynamic_value.GetObjectDescription()
100 if desc:
101 print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
102 else:
103 print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
104 else:
105 print expr_sbvalue.error
106
107def heap_ptr_refs(debugger, command, result, dict):
Greg Claytone93e24f2012-04-11 16:27:06 +0000108 command_args = shlex.split(command)
109 usage = "usage: %prog [options] <PATH> [PATH ...]"
Greg Clayton96666442012-04-11 18:30:53 +0000110 description='''Searches the heap for pointer references on darwin user space programs.
111
112 Any matches that were found will dump the malloc blocks that contain the pointers
113 and might be able to print what kind of objects the pointers are contained in using
114 dynamic type information from the program.'''
115 parser = optparse.OptionParser(description=description, prog='heap_ptr_refs',usage=usage)
Greg Claytone93e24f2012-04-11 16:27:06 +0000116 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
Greg Clayton96666442012-04-11 18:30:53 +0000117 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
Greg Claytone93e24f2012-04-11 16:27:06 +0000118 try:
119 (options, args) = parser.parse_args(command_args)
120 except:
121 return
Greg Clayton96666442012-04-11 18:30:53 +0000122
123 options.type = 'pointer'
Greg Claytone93e24f2012-04-11 16:27:06 +0000124
125 if args:
126
127 for data in args:
Greg Clayton96666442012-04-11 18:30:53 +0000128 heap_search (options, data)
Greg Claytone93e24f2012-04-11 16:27:06 +0000129 else:
Greg Clayton96666442012-04-11 18:30:53 +0000130 print 'error: no pointer arguments were given'
Greg Claytone93e24f2012-04-11 16:27:06 +0000131
Greg Clayton96666442012-04-11 18:30:53 +0000132def heap_cstr_refs(debugger, command, result, dict):
133 command_args = shlex.split(command)
134 usage = "usage: %prog [options] <PATH> [PATH ...]"
135 description='''Searches the heap for C string references on darwin user space programs.
136
137 Any matches that were found will dump the malloc blocks that contain the C strings
138 and might be able to print what kind of objects the pointers are contained in using
139 dynamic type information from the program.'''
140 parser = optparse.OptionParser(description=description, prog='heap_cstr_refs',usage=usage)
141 parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
142 parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
143 try:
144 (options, args) = parser.parse_args(command_args)
145 except:
146 return
147
148 options.type = 'cstr'
149
150 if args:
151
152 for data in args:
153 heap_search (options, data)
154 else:
155 print 'error: no c string arguments were given to search for'
Greg Claytone93e24f2012-04-11 16:27:06 +0000156
157def __lldb_init_module (debugger, dict):
158 # This initializer is being run from LLDB in the embedded command interpreter
159 # Add any commands contained in this module to LLDB
Greg Clayton96666442012-04-11 18:30:53 +0000160 libheap_dylib_path = os.path.dirname(__file__) + '/libheap.dylib'
161 debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
162 debugger.HandleCommand('command script add -f heap.heap_ptr_refs heap_ptr_refs')
163 debugger.HandleCommand('command script add -f heap.heap_cstr_refs heap_cstr_refs')
164 print '"heap_ptr_refs" and "heap_cstr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
Greg Claytone93e24f2012-04-11 16:27:06 +0000165
166
167
168