heap.py revision 1dae6f39248e38ac84fc20c8b4c26e11bfcc19b7
1e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#!/usr/bin/python 2e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 3e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 41dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# This module is designed to live inside the "lldb" python package 51dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# in the "lldb.macosx" package. To use this in the embedded python 61dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# interpreter using "lldb" just import it: 7e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton# 81dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# (lldb) script import lldb.macosx.heap 9e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton#---------------------------------------------------------------------- 10e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 11e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport lldb 12e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport commands 13e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport optparse 149666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Claytonimport os 151dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonimport os.path 16e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport shlex 171dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonimport string 181dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonimport tempfile 196f2f0ab38426bdb5ed347f057ba57248667a40c3Greg Claytonimport lldb.utils.symbolication 20e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 211dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytong_libheap_dylib_dir = None 221dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytong_libheap_dylib_dict = dict() 231dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton 249098fee45dc61264a9fe54d075751e76f7de610fGreg Claytondef load_dylib(): 259098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if lldb.target: 261dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton global g_libheap_dylib_dir 271dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton global g_libheap_dylib_dict 281dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton triple = lldb.target.triple 291dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton if triple not in g_libheap_dylib_dict: 301dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton if not g_libheap_dylib_dir: 311dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton g_libheap_dylib_dir = tempfile.mkdtemp() 321dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton triple_dir = g_libheap_dylib_dir + '/' + triple 331dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton if not os.path.exists(triple_dir): 341dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton os.mkdir(triple_dir) 351dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton libheap_dylib_path = triple_dir + '/libheap.dylib' 361dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton g_libheap_dylib_dict[triple] = libheap_dylib_path 371dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton libheap_dylib_path = g_libheap_dylib_dict[triple] 389098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if not os.path.exists(libheap_dylib_path): 391dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton heap_code_directory = os.path.dirname(__file__) + '/heap' 401dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton make_command = '(cd "%s" ; make EXE="%s" ARCH=%s)' % (heap_code_directory, libheap_dylib_path, string.split(triple, '-')[0]) 411dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton #print make_command 421dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton make_output = commands.getoutput(make_command) 431dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton #print make_output 449098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if os.path.exists(libheap_dylib_path): 459098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton libheap_dylib_spec = lldb.SBFileSpec(libheap_dylib_path) 469098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if lldb.target.FindModule(libheap_dylib_spec): 479098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return None # success, 'libheap.dylib' already loaded 489098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if lldb.process: 499098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton state = lldb.process.state 509098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if state == lldb.eStateStopped: 519098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton (libheap_dylib_path) 529098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton error = lldb.SBError() 539098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton image_idx = lldb.process.LoadImage(libheap_dylib_spec, error) 549098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if error.Success(): 559098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return None 569098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 579098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if error: 589098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: %s' % error 599098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 609098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: "process load \'%s\'" failed' % libheap_dylib_spec 619098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 629098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: process is not stopped' 639098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 649098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: invalid process' 659098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 669098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: file does not exist "%s"' % libheap_dylib_path 679098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 689098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 'error: invalid target' 699098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton 709098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton debugger.HandleCommand('process load "%s"' % libheap_dylib_path) 719098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton 7293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Claytondef add_common_options(parser): 7393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False) 7493e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False) 7593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False) 7693e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None) 779098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton 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) 789098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton #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) 7993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton 809666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Claytondef heap_search(options, arg_str): 819098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton dylid_load_err = load_dylib() 829098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if dylid_load_err: 839098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton print dylid_load_err 849098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton return 859666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr = None 86bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = arg_str 8793e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton default_memory_format = "Y" # 'Y' is "bytes with ASCII" format 8893e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton #memory_chunk_size = 1 899666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if options.type == 'pointer': 901dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton expr = 'find_pointer_in_heap((void *)%s)' % (arg_str) 91bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block containing pointer %s' % arg_str 9293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton default_memory_format = "A" # 'A' is "address" format 9393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton #memory_chunk_size = lldb.process.GetAddressByteSize() 949666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton elif options.type == 'cstr': 959666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr = 'find_cstring_in_heap("%s")' % arg_str 96bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block containing "%s"' % arg_str 97bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton elif options.type == 'addr': 98f5902cb7d5d29e72e5aba0932dda299d7aaed570Greg Clayton expr = 'find_block_for_address((void *)%s)' % arg_str 99bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton arg_str_description = 'malloc block for %s' % arg_str 1009666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 1019666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type 1029666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton return 1039666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 1049666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton expr_sbvalue = lldb.frame.EvaluateExpression (expr) 1059666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if expr_sbvalue.error.Success(): 1069666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if expr_sbvalue.unsigned: 1079666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton match_value = lldb.value(expr_sbvalue) 1089666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton i = 0 1099666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton while 1: 1109666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton match_entry = match_value[i]; i += 1 1119666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton malloc_addr = match_entry.addr.sbvalue.unsigned 1129666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if malloc_addr == 0: 1139666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton break 1149666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton malloc_size = int(match_entry.size) 1159666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton offset = int(match_entry.offset) 1169666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget) 1179666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton # If the type is still 'void *' then we weren't able to figure 1189666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton # out a dynamic type for the malloc_addr 1199666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton type_name = dynamic_value.type.name 120bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr) 121bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if offset != 0: 122bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ' + %u' % (offset) 123bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', size = %u' % (malloc_size) 1249666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if type_name == 'void *': 1259666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if options.type == 'pointer' and malloc_size == 4096: 1269666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton error = lldb.SBError() 1279666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error)) 1289666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if data == '\xa1\xa1\xa1\xa1AUTORELEASE!': 129bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', type = (AUTORELEASE!)' 13093e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton print description 131bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 132bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description += ', type = %s' % (type_name) 133bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton derefed_dynamic_value = dynamic_value.deref 134bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = None 135bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if derefed_dynamic_value: 136bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton derefed_dynamic_type = derefed_dynamic_value.type 137bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetFieldAtIndex(0) 138bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton search_bases = False 139bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member: 140bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member.GetOffsetInBytes() <= offset: 141bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfFields()): 142bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetFieldAtIndex(field_idx) 143bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member_byte_offset = member.GetOffsetInBytes() 144bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member_byte_offset == offset: 145bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = member 146bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton break 147bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 148bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton search_bases = True 1499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 1509666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton search_bases = True 151bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 152bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if not ivar_member and search_bases: 153bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()): 154bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx) 1559666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton member_byte_offset = member.GetOffsetInBytes() 1569666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if member_byte_offset == offset: 1579666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton ivar_member = member 1589666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton break 159bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if not ivar_member: 160bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()): 161bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx) 162bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton member_byte_offset = member.GetOffsetInBytes() 163bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if member_byte_offset == offset: 164bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton ivar_member = member 165bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton break 1669666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if ivar_member: 167bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description +=', ivar = %s' % (ivar_member.name) 168bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 169bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print description 170bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if derefed_dynamic_value: 171bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print derefed_dynamic_value 172bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if options.print_object_description: 173bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton desc = dynamic_value.GetObjectDescription() 174bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if desc: 175bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc) 17693e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton if options.memory: 17793e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton memory_format = options.format 17893e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton if not memory_format: 17993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton memory_format = default_memory_format 18093e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton cmd_result = lldb.SBCommandReturnObject() 18193e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton #count = malloc_size / memory_chunk_size 18293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size) 18393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result) 18493e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton print cmd_result.GetOutput() 1859098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if options.stack: 1866f2f0ab38426bdb5ed347f057ba57248667a40c3Greg Clayton symbolicator = lldb.utils.symbolication.Symbolicator() 1879098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton symbolicator.target = lldb.target 1889098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton expr_str = "g_stack_frames_count = sizeof(g_stack_frames)/sizeof(uint64_t); (int)__mach_stack_logging_get_frames((unsigned)mach_task_self(), 0x%xull, g_stack_frames, g_stack_frames_count, &g_stack_frames_count)" % (malloc_addr) 1899098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton #print expr_str 1909098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton expr = lldb.frame.EvaluateExpression (expr_str); 1919098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton expr_error = expr.GetError() 1929098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if expr_error.Success(): 1939098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton err = expr.unsigned 1949098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if err: 1959098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton print 'error: __mach_stack_logging_get_frames() returned error %i' % (err) 1969098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 1979098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton count_expr = lldb.frame.EvaluateExpression ("g_stack_frames_count") 1989098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton count = count_expr.unsigned 1999098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton #print 'g_stack_frames_count is %u' % (count) 2009098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if count > 0: 2019098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frame_idx = 0 2029098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frames_expr = lldb.value(lldb.frame.EvaluateExpression ("g_stack_frames")) 2039098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton done = False 2049098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton for stack_frame_idx in range(count): 2059098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if not done: 2069098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frame_load_addr = int(frames_expr[stack_frame_idx]) 2079098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if frame_load_addr >= 0x1000: 2089098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frames = symbolicator.symbolicate(frame_load_addr) 2099098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton if frames: 2109098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton for frame in frames: 2119098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton print '[%3u] %s' % (frame_idx, frame) 2129098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frame_idx += 1 2139098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 2149098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton print '[%3u] 0x%x' % (frame_idx, frame_load_addr) 2159098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton frame_idx += 1 2169098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 2179098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton done = True 2189098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton else: 2199098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton print 'error: %s' % (expr_error) 2209666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 2219666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print '%s %s was not found in any malloc blocks' % (options.type, arg_str) 2229666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 223bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print expr_sbvalue.error 224bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print 2259666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 226bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef ptr_refs(debugger, command, result, dict): 227e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton command_args = shlex.split(command) 228bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <PTR> [PTR ...]" 2299666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton description='''Searches the heap for pointer references on darwin user space programs. 2309666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 2319666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton Any matches that were found will dump the malloc blocks that contain the pointers 2329666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton and might be able to print what kind of objects the pointers are contained in using 233bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton dynamic type information in the program.''' 234bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage) 23593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton add_common_options(parser) 236e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton try: 237e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton (options, args) = parser.parse_args(command_args) 238e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton except: 239e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton return 2409666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 2419666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton options.type = 'pointer' 242e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 243e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton if args: 244e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 245e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton for data in args: 2469666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton heap_search (options, data) 247e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton else: 2489666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: no pointer arguments were given' 2499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 250bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef cstr_refs(debugger, command, result, dict): 2519666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton command_args = shlex.split(command) 252bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <CSTR> [CSTR ...]" 2539666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton description='''Searches the heap for C string references on darwin user space programs. 2549666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 2559666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton Any matches that were found will dump the malloc blocks that contain the C strings 2569666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton and might be able to print what kind of objects the pointers are contained in using 257bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton dynamic type information in the program.''' 258bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage) 25993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton add_common_options(parser) 2609666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton try: 2619666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton (options, args) = parser.parse_args(command_args) 2629666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton except: 2639666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton return 2649666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 2659666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton options.type = 'cstr' 266e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 2679666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton if args: 2689666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton 2699666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton for data in args: 2709666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton heap_search (options, data) 2719666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton else: 2729666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton print 'error: no c string arguments were given to search for' 273e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 274bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef malloc_info(debugger, command, result, dict): 275bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton command_args = shlex.split(command) 276bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton usage = "usage: %prog [options] <ADDR> [ADDR ...]" 277bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton description='''Searches the heap a malloc block that contains the addresses specified as arguments. 278bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 279bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton Any matches that were found will dump the malloc blocks that match or contain 280bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton the specified address. The matching blocks might be able to show what kind 281bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton of objects they are using dynamic type information in the program.''' 282bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage) 28393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton add_common_options(parser) 284bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton try: 285bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton (options, args) = parser.parse_args(command_args) 286bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton except: 287bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton return 288bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 289bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton options.type = 'addr' 290bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 291bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton if args: 292bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 293bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton for data in args: 294bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton heap_search (options, data) 295bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton else: 296bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton print 'error: no c string arguments were given to search for' 297bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton 2981dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonif __name__ == '__main__': 2991dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton lldb.debugger = lldb.SBDebugger.Create() 3001dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton 3011dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# This initializer is being run from LLDB in the embedded command interpreter 3021dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton# Add any commands contained in this module to LLDB 3031dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonlldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.ptr_refs ptr_refs') 3041dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonlldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs') 3051dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonlldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info') 3061dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonprint '"ptr_refs", "cstr_refs", and "malloc_info" commands have been installed, use the "--help" options on these commands for detailed help.' 307e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 308e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 309e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 310e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton 311