heap.py revision 9098fee45dc61264a9fe54d075751e76f7de610f
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
239098fee45dc61264a9fe54d075751e76f7de610fGreg Claytonimport symbolication # from lldb/examples/python/symbolication.py
24e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
259098fee45dc61264a9fe54d075751e76f7de610fGreg Claytondef load_dylib():
269098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton    if lldb.target:
279098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        python_module_directory = os.path.dirname(__file__)
289098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        libheap_dylib_path = python_module_directory + '/libheap.dylib'
299098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        if not os.path.exists(libheap_dylib_path):
309098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            make_command = '(cd "%s" ; make)' % python_module_directory
319098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            print make_command
329098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            print commands.getoutput(make_command)
339098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        if os.path.exists(libheap_dylib_path):
349098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            libheap_dylib_spec = lldb.SBFileSpec(libheap_dylib_path)
359098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            if lldb.target.FindModule(libheap_dylib_spec):
369098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                return None # success, 'libheap.dylib' already loaded
379098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            if lldb.process:
389098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                state = lldb.process.state
399098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                if state == lldb.eStateStopped:
409098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    (libheap_dylib_path)
419098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    error = lldb.SBError()
429098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    image_idx = lldb.process.LoadImage(libheap_dylib_spec, error)
439098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    if error.Success():
449098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        return None
459098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    else:
469098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        if error:
479098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            return 'error: %s' % error
489098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        else:
499098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            return 'error: "process load \'%s\'" failed' % libheap_dylib_spec
509098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                else:
519098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    return 'error: process is not stopped'
529098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            else:
539098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                return 'error: invalid process'
549098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        else:
559098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton            return 'error: file does not exist "%s"' % libheap_dylib_path
569098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton    else:
579098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        return 'error: invalid target'
589098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton
599098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton    debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
609098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton
6193e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Claytondef add_common_options(parser):
6293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
6393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
6493e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
6593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
669098fee45dc61264a9fe54d075751e76f7de610fGreg 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)
679098fee45dc61264a9fe54d075751e76f7de610fGreg 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)
6893e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton
699666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Claytondef heap_search(options, arg_str):
709098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton    dylid_load_err = load_dylib()
719098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton    if dylid_load_err:
729098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        print dylid_load_err
739098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton        return
749666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    expr = None
75bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    arg_str_description = arg_str
7693e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    default_memory_format = "Y" # 'Y' is "bytes with ASCII" format
7793e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    #memory_chunk_size = 1
789666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    if options.type == 'pointer':
79f5902cb7d5d29e72e5aba0932dda299d7aaed570Greg Clayton        expr = 'find_pointer_in_heap((void *)%s)' % arg_str
80bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        arg_str_description = 'malloc block containing pointer %s' % arg_str
8193e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton        default_memory_format = "A" # 'A' is "address" format
8293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton        #memory_chunk_size = lldb.process.GetAddressByteSize()
839666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    elif options.type == 'cstr':
849666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        expr = 'find_cstring_in_heap("%s")' % arg_str
85bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        arg_str_description = 'malloc block containing "%s"' % arg_str
86bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    elif options.type == 'addr':
87f5902cb7d5d29e72e5aba0932dda299d7aaed570Greg Clayton        expr = 'find_block_for_address((void *)%s)' % arg_str
88bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        arg_str_description = 'malloc block for %s' % arg_str
899666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    else:
909666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
919666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        return
929666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
939666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    expr_sbvalue = lldb.frame.EvaluateExpression (expr)
949666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    if expr_sbvalue.error.Success():
959666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        if expr_sbvalue.unsigned:
969666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            match_value = lldb.value(expr_sbvalue)
979666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            i = 0
989666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            while 1:
999666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                match_entry = match_value[i]; i += 1
1009666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                malloc_addr = match_entry.addr.sbvalue.unsigned
1019666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                if malloc_addr == 0:
1029666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                    break
1039666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                malloc_size = int(match_entry.size)
1049666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                offset = int(match_entry.offset)
1059666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
1069666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                # If the type is still 'void *' then we weren't able to figure
1079666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                # out a dynamic type for the malloc_addr
1089666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                type_name = dynamic_value.type.name
109bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
110bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                if offset != 0:
111bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    description += ' + %u' % (offset)
112bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                description += ', size = %u' % (malloc_size)
1139666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                if type_name == 'void *':
1149666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                    if options.type == 'pointer' and malloc_size == 4096:
1159666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                        error = lldb.SBError()
1169666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                        data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
1179666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                        if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
118bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            description += ', type = (AUTORELEASE!)'
11993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    print description
120bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                else:
121bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    description += ', type = %s' % (type_name)
122bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    derefed_dynamic_value = dynamic_value.deref
123bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    ivar_member = None
124bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    if derefed_dynamic_value:
125bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        derefed_dynamic_type = derefed_dynamic_value.type
126bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        member = derefed_dynamic_type.GetFieldAtIndex(0)
127bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        search_bases = False
128bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        if member:
129bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            if member.GetOffsetInBytes() <= offset:
130bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
131bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
132bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    member_byte_offset = member.GetOffsetInBytes()
133bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    if member_byte_offset == offset:
134bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                        ivar_member = member
135bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                        break
136bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            else:
137bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                search_bases = True
1389666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                        else:
1399666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                            search_bases = True
140bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
141bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        if not ivar_member and search_bases:
142bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
143bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
1449666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                                member_byte_offset = member.GetOffsetInBytes()
1459666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                                if member_byte_offset == offset:
1469666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                                    ivar_member = member
1479666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                                    break
148bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            if not ivar_member:
149bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
150bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
151bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    member_byte_offset = member.GetOffsetInBytes()
152bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                    if member_byte_offset == offset:
153bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                        ivar_member = member
154bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                                        break
1559666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                    if ivar_member:
156bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        description +=', ivar = %s' % (ivar_member.name)
157bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
158bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    print description
159bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    if derefed_dynamic_value:
160bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        print derefed_dynamic_value
161bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                    if options.print_object_description:
162bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        desc = dynamic_value.GetObjectDescription()
163bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                        if desc:
164bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton                            print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
16593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                if options.memory:
16693e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    memory_format = options.format
16793e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    if not memory_format:
16893e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                        memory_format = default_memory_format
16993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    cmd_result = lldb.SBCommandReturnObject()
17093e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    #count = malloc_size / memory_chunk_size
17193e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size)
17293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
17393e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton                    print cmd_result.GetOutput()
1749098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                if options.stack:
1759098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    symbolicator = symbolication.Symbolicator()
1769098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    symbolicator.target = lldb.target
1779098fee45dc61264a9fe54d075751e76f7de610fGreg 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)
1789098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    #print expr_str
1799098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    expr = lldb.frame.EvaluateExpression (expr_str);
1809098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    expr_error = expr.GetError()
1819098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    if expr_error.Success():
1829098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        err = expr.unsigned
1839098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        if err:
1849098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            print 'error: __mach_stack_logging_get_frames() returned error %i' % (err)
1859098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        else:
1869098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            count_expr = lldb.frame.EvaluateExpression ("g_stack_frames_count")
1879098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            count = count_expr.unsigned
1889098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            #print 'g_stack_frames_count is %u' % (count)
1899098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                            if count > 0:
1909098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                frame_idx = 0
1919098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                frames_expr = lldb.value(lldb.frame.EvaluateExpression ("g_stack_frames"))
1929098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                done = False
1939098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                for stack_frame_idx in range(count):
1949098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                    if not done:
1959098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                        frame_load_addr = int(frames_expr[stack_frame_idx])
1969098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                        if frame_load_addr >= 0x1000:
1979098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                            frames = symbolicator.symbolicate(frame_load_addr)
1989098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                            if frames:
1999098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                                for frame in frames:
2009098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                                    print '[%3u] %s' % (frame_idx, frame)
2019098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                                    frame_idx += 1
2029098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                            else:
2039098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                                print '[%3u] 0x%x' % (frame_idx, frame_load_addr)
2049098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                                frame_idx += 1
2059098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                        else:
2069098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                                            done = True
2079098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                    else:
2089098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton                        print 'error: %s' % (expr_error)
2099666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        else:
2109666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
2119666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    else:
212bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        print expr_sbvalue.error
213bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    print
2149666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
215bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef ptr_refs(debugger, command, result, dict):
216e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    command_args = shlex.split(command)
217bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    usage = "usage: %prog [options] <PTR> [PTR ...]"
2189666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    description='''Searches the heap for pointer references on darwin user space programs.
2199666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
2209666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    Any matches that were found will dump the malloc blocks that contain the pointers
2219666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    and might be able to print what kind of objects the pointers are contained in using
222bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    dynamic type information in the program.'''
223bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
22493e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
225e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    try:
226e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton        (options, args) = parser.parse_args(command_args)
227e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    except:
228e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton        return
2299666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
2309666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    options.type = 'pointer'
231e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
232e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    if args:
233e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
234e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton        for data in args:
2359666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            heap_search (options, data)
236e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    else:
2379666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        print 'error: no pointer arguments were given'
2389666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
239bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef cstr_refs(debugger, command, result, dict):
2409666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    command_args = shlex.split(command)
241bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    usage = "usage: %prog [options] <CSTR> [CSTR ...]"
2429666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    description='''Searches the heap for C string references on darwin user space programs.
2439666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
2449666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    Any matches that were found will dump the malloc blocks that contain the C strings
2459666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    and might be able to print what kind of objects the pointers are contained in using
246bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    dynamic type information in the program.'''
247bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
24893e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
2499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    try:
2509666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        (options, args) = parser.parse_args(command_args)
2519666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    except:
2529666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        return
2539666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
2549666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    options.type = 'cstr'
255e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
2569666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    if args:
2579666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
2589666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        for data in args:
2599666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            heap_search (options, data)
2609666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    else:
2619666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        print 'error: no c string arguments were given to search for'
262e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
263bff78410b94d0b52956e3c6f2966b25a9b799366Greg Claytondef malloc_info(debugger, command, result, dict):
264bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    command_args = shlex.split(command)
265bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    usage = "usage: %prog [options] <ADDR> [ADDR ...]"
266bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    description='''Searches the heap a malloc block that contains the addresses specified as arguments.
267bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
268bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    Any matches that were found will dump the malloc blocks that match or contain
269bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    the specified address. The matching blocks might be able to show what kind
270bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    of objects they are using dynamic type information in the program.'''
271bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
27293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
273bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    try:
274bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        (options, args) = parser.parse_args(command_args)
275bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    except:
276bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        return
277bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
278bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    options.type = 'addr'
279bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
280bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    if args:
281bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
282bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        for data in args:
283bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton            heap_search (options, data)
284bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    else:
285bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        print 'error: no c string arguments were given to search for'
286bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
287e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytondef __lldb_init_module (debugger, dict):
288e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    # This initializer is being run from LLDB in the embedded command interpreter
289e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    # Add any commands contained in this module to LLDB
290bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    debugger.HandleCommand('command script add -f heap.ptr_refs ptr_refs')
291bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    debugger.HandleCommand('command script add -f heap.cstr_refs cstr_refs')
292bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    debugger.HandleCommand('command script add -f heap.malloc_info malloc_info')
293bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    print '"ptr_refs", "cstr_refs", and "malloc_info" commands have been installed, use the "--help" options on these commands for detailed help.'
294e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
295e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
296e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
297e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
298