heap.py revision bff78410b94d0b52956e3c6f2966b25a9b799366
1e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#!/usr/bin/python 2e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 3e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 4e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# Be sure to add the python path that points to the LLDB shared library. 5e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 6e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# # To use this in the embedded python interpreter using "lldb" just 7e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# import it with the full path using the "command script import" 8e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# command 9e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# (lldb) command script import /path/to/heap.py 10e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 11e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# For the shells csh, tcsh: 12e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./heap.py ) 13e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 14e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# For the shells sh, bash: 15e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./heap.py 16e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 17e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 18e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport lldb 19e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport commands 20e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport optparse 219666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Claytonimport os 22e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport shlex 23e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 249666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Claytondef heap_search(options, arg_str): 259666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr = None 26bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = arg_str 279666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if options.type == 'pointer': 28bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton expr = 'find_pointer_in_heap(%s)' % arg_str 29bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block containing pointer %s' % arg_str 309666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton elif options.type == 'cstr': 319666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr = 'find_cstring_in_heap("%s")' % arg_str 32bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block containing "%s"' % arg_str 33bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton elif options.type == 'addr': 34bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton expr = 'find_block_for_address(%s)' % arg_str 35bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block for %s' % arg_str 369666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 379666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type 389666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton return 399666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 409666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr_sbvalue = lldb.frame.EvaluateExpression (expr) 419666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if expr_sbvalue.error.Success(): 429666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if expr_sbvalue.unsigned: 439666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton match_value = lldb.value(expr_sbvalue) 449666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton i = 0 459666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton while 1: 469666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton match_entry = match_value[i]; i += 1 479666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton malloc_addr = match_entry.addr.sbvalue.unsigned 489666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if malloc_addr == 0: 499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton break 509666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton malloc_size = int(match_entry.size) 519666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton offset = int(match_entry.offset) 529666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget) 539666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton # If the type is still 'void *' then we weren't able to figure 549666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton # out a dynamic type for the malloc_addr 559666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton type_name = dynamic_value.type.name 56bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr) 57bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if offset != 0: 58bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ' + %u' % (offset) 59bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', size = %u' % (malloc_size) 609666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if type_name == 'void *': 619666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if options.type == 'pointer' and malloc_size == 4096: 629666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton error = lldb.SBError() 639666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error)) 649666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': 65bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', type = (AUTORELEASE!)' 66bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print description 679666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton continue 68bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 69bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', type = %s' % (type_name) 70bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton derefed_dynamic_value = dynamic_value.deref 71bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = None 72bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if derefed_dynamic_value: 73bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton derefed_dynamic_type = derefed_dynamic_value.type 74bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetFieldAtIndex(0) 75bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton search_bases = False 76bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member: 77bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member.GetOffsetInBytes() <= offset: 78bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfFields()): 79bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetFieldAtIndex(field_idx) 80bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member_byte_offset = member.GetOffsetInBytes() 81bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member_byte_offset == offset: 82bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = member 83bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton break 84bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 85bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton search_bases = True 869666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 879666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton search_bases = True 88bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 89bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if not ivar_member and search_bases: 90bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()): 91bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx) 929666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton member_byte_offset = member.GetOffsetInBytes() 939666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if member_byte_offset == offset: 949666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton ivar_member = member 959666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton break 96bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if not ivar_member: 97bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()): 98bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx) 99bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member_byte_offset = member.GetOffsetInBytes() 100bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member_byte_offset == offset: 101bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = member 102bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton break 1039666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if ivar_member: 104bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description +=', ivar = %s' % (ivar_member.name) 105bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 106bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print description 107bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if derefed_dynamic_value: 108bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print derefed_dynamic_value 109bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if options.print_object_description: 110bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton desc = dynamic_value.GetObjectDescription() 111bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if desc: 112bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) 1139666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 1149666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print '%s %s was not found in any malloc blocks' % (options.type, arg_str) 1159666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 116bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print expr_sbvalue.error 117bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print 1189666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 119bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef ptr_refs(debugger, command, result, dict): 120e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton command_args = shlex.split(command) 121bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <PTR> [PTR ...]" 1229666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton description='''Searches the heap for pointer references on darwin user space programs. 1239666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1249666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton Any matches that were found will dump the malloc blocks that contain the pointers 1259666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton and might be able to print what kind of objects the pointers are contained in using 126bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton dynamic type information in the program.''' 127bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage) 128e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 1299666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False) 130bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False) 131e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton try: 132e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton (options, args) = parser.parse_args(command_args) 133e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton except: 134e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton return 1359666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1369666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton options.type = 'pointer' 137e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 138e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if args: 139e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 140e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton for data in args: 1419666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton heap_search (options, data) 142e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 1439666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: no pointer arguments were given' 1449666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 145bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef cstr_refs(debugger, command, result, dict): 1469666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton command_args = shlex.split(command) 147bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <CSTR> [CSTR ...]" 1489666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton description='''Searches the heap for C string references on darwin user space programs. 1499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1509666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton Any matches that were found will dump the malloc blocks that contain the C strings 1519666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton and might be able to print what kind of objects the pointers are contained in using 152bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton dynamic type information in the program.''' 153bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage) 1549666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 1559666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False) 156bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False) 1579666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton try: 1589666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton (options, args) = parser.parse_args(command_args) 1599666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton except: 1609666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton return 1619666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1629666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton options.type = 'cstr' 163e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 1649666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if args: 1659666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1669666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton for data in args: 1679666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton heap_search (options, data) 1689666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 1699666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: no c string arguments were given to search for' 170e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 171bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef malloc_info(debugger, command, result, dict): 172bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton command_args = shlex.split(command) 173bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <ADDR> [ADDR ...]" 174bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description='''Searches the heap a malloc block that contains the addresses specified as arguments. 175bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 176bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton Any matches that were found will dump the malloc blocks that match or contain 177bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton the specified address. The matching blocks might be able to show what kind 178bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton of objects they are using dynamic type information in the program.''' 179bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage) 180bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 181bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False) 182bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser.add_option('-m', '--memory', action='store_true', dest='show_memory', help='dump the memory for each matching block', default=False) 183bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton try: 184bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton (options, args) = parser.parse_args(command_args) 185bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton except: 186bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton return 187bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 188bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton options.type = 'addr' 189bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 190bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if args: 191bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 192bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for data in args: 193bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton heap_search (options, data) 194bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 195bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print 'error: no c string arguments were given to search for' 196bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 197e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytondef __lldb_init_module (debugger, dict): 198e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # This initializer is being run from LLDB in the embedded command interpreter 199e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton # Add any commands contained in this module to LLDB 2009666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton libheap_dylib_path = os.path.dirname(__file__) + '/libheap.dylib' 2019666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton debugger.HandleCommand('process load "%s"' % libheap_dylib_path) 202bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton debugger.HandleCommand('command script add -f heap.ptr_refs ptr_refs') 203bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton debugger.HandleCommand('command script add -f heap.cstr_refs cstr_refs') 204bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton debugger.HandleCommand('command script add -f heap.malloc_info malloc_info') 205bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print '"ptr_refs", "cstr_refs", and "malloc_info" commands have been installed, use the "--help" options on these commands for detailed help.' 206e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 207e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 208e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 209e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 210