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