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
164c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Claytonimport re
17e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Claytonimport shlex
181dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonimport string
191dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonimport tempfile
206f2f0ab38426bdb5ed347f057ba57248667a40c3Greg Claytonimport lldb.utils.symbolication
21e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
221dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytong_libheap_dylib_dir = None
231dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytong_libheap_dylib_dict = dict()
241dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton
25ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytondef get_iterate_memory_expr(options, process, user_init_code, user_return_code):
26ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    expr = '''
27549294a273c684afbc3227a02119bbbce79fd810Greg Claytontypedef unsigned natural_t;
28849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef uintptr_t vm_size_t;
29849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef uintptr_t vm_address_t;
30849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef natural_t task_t;
31849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef int kern_return_t;
32849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton#define KERN_SUCCESS 0
33ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef void (*range_callback_t)(task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size);
34ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton''';
35ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    if options.search_vm_regions:
36ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        expr += '''
37ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef int vm_prot_t;
38ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef unsigned int vm_inherit_t;
39ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef unsigned long long	memory_object_offset_t;
40ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef unsigned int boolean_t;
41ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef int vm_behavior_t;
42ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint32_t vm32_object_id_t;
43ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef natural_t mach_msg_type_number_t;
44ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t mach_vm_address_t;
45ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t mach_vm_offset_t;
46ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t mach_vm_size_t;
47ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t vm_map_offset_t;
48ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t vm_map_address_t;
49ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef uint64_t vm_map_size_t;
50ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define	VM_PROT_NONE ((vm_prot_t) 0x00)
51ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define VM_PROT_READ ((vm_prot_t) 0x01)
52ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define VM_PROT_WRITE ((vm_prot_t) 0x02)
53ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define VM_PROT_EXECUTE ((vm_prot_t) 0x04)
54ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontypedef struct vm_region_submap_short_info_data_64_t {
55ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    vm_prot_t protection;
56ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    vm_prot_t max_protection;
57ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    vm_inherit_t inheritance;
58ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    memory_object_offset_t offset;		// offset into object/map
59ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned int user_tag;	// user tag on map entry
60ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned int ref_count;	 // obj/map mappers, etc
61ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned short shadow_depth; 	// only for obj
62ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned char external_pager;  // only for obj
63ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned char share_mode;	// see enumeration
64ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    boolean_t is_submap;	// submap vs obj
65ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    vm_behavior_t behavior;	// access behavior hint
66ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    vm32_object_id_t object_id;	// obj/map name, not a handle
67ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    unsigned short user_wired_count;
68ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton} vm_region_submap_short_info_data_64_t;
69ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 ((mach_msg_type_number_t)(sizeof(vm_region_submap_short_info_data_64_t)/sizeof(int)))''';
70ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if user_init_code:
71ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += user_init_code;
72ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        expr += '''
73ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytontask_t task = (task_t)mach_task_self();
74ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonmach_vm_address_t vm_region_base_addr;
75ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonmach_vm_size_t vm_region_size;
76ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonnatural_t vm_region_depth;
77ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonvm_region_submap_short_info_data_64_t vm_region_info;
78ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonkern_return_t err;
79ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonfor (vm_region_base_addr = 0, vm_region_size = 1; vm_region_size != 0; vm_region_base_addr += vm_region_size)
80ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton{
81ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    mach_msg_type_number_t vm_region_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
82ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    err = (kern_return_t)mach_vm_region_recurse (task,
83ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                 &vm_region_base_addr,
84ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                 &vm_region_size,
85ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                 &vm_region_depth,
86ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                 &vm_region_info,
87ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                 &vm_region_info_size);
88ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    if (err)
89ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        break;
90ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    // Check all read + write regions. This will cover the thread stacks
91ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    // and any regions of memory like __DATA segments, that might contain
92ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    // data we are looking for
93ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    if (vm_region_info.protection & VM_PROT_WRITE &&
94ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        vm_region_info.protection & VM_PROT_READ)
95ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    {
96ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        baton.callback (task,
97ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        &baton,
98ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        64,
99ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        vm_region_base_addr,
100ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        vm_region_size);
101ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    }
102ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton}'''
103ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    else:
104ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if options.search_stack:
105ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += get_thread_stack_ranges_struct (process)
106ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if options.search_segments:
107ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += get_sections_ranges_struct (process)
108ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if user_init_code:
109ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += user_init_code
110ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if options.search_heap:
111ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += '''
112849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton#define MALLOC_PTR_IN_USE_RANGE_TYPE 1
113849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct vm_range_t {
114849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    vm_address_t	address;
115849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    vm_size_t		size;
116849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} vm_range_t;
117849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef kern_return_t (*memory_reader_t)(task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory);
118849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef void (*vm_range_recorder_t)(task_t task, void *baton, unsigned type, vm_range_t *range, unsigned size);
119849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct malloc_introspection_t {
120849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    kern_return_t (*enumerator)(task_t task, void *, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t recorder); /* enumerates all the malloc pointers in use */
121849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} malloc_introspection_t;
122849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct malloc_zone_t {
123849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *reserved1[12];
124849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    struct malloc_introspection_t	*introspect;
125849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} malloc_zone_t;
126849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonmemory_reader_t task_peek = [](task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory) -> kern_return_t {
127849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    *local_memory = (void*) remote_address;
128849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return KERN_SUCCESS;
129849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
130849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonvm_address_t *zones = 0;
131ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonunsigned int num_zones = 0;task_t task = 0;
132849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonkern_return_t err = (kern_return_t)malloc_get_all_zones (task, task_peek, &zones, &num_zones);
133849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonif (KERN_SUCCESS == err)
134849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton{
135849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    for (unsigned int i=0; i<num_zones; ++i)
136849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    {
137849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        const malloc_zone_t *zone = (const malloc_zone_t *)zones[i];
138849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if (zone && zone->introspect)
139849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            zone->introspect->enumerator (task,
140849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          &baton,
141849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          MALLOC_PTR_IN_USE_RANGE_TYPE,
142849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          (vm_address_t)zone,
143849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          task_peek,
144849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          [] (task_t task, void *baton, unsigned type, vm_range_t *ranges, unsigned size) -> void
145849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          {
146849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                              range_callback_t callback = ((callback_baton_t *)baton)->callback;
147849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                              for (unsigned i=0; i<size; ++i)
148849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                              {
149849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                                  callback (task, baton, type, ranges[i].address, ranges[i].size);
150849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                              }
151849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                          });
152849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
153ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton}'''
154ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton
155ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if options.search_stack:
156ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += '''
157549294a273c684afbc3227a02119bbbce79fd810Greg Clayton// Call the callback for the thread stack ranges
158ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonfor (uint32_t i=0; i<NUM_STACKS; ++i) {
159549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    range_callback(task, &baton, 8, stacks[i].base, stacks[i].size);
160ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    if (STACK_RED_ZONE_SIZE > 0) {
161ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        range_callback(task, &baton, 16, stacks[i].base - STACK_RED_ZONE_SIZE, STACK_RED_ZONE_SIZE);
162ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    }
163ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton}
164ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    '''
165ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton
166ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        if options.search_segments:
167ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr += '''
168549294a273c684afbc3227a02119bbbce79fd810Greg Clayton// Call the callback for all segments
169549294a273c684afbc3227a02119bbbce79fd810Greg Claytonfor (uint32_t i=0; i<NUM_SEGMENTS; ++i)
170ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    range_callback(task, &baton, 32, segments[i].base, segments[i].size);'''
171ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton
172ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    if user_return_code:
173ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        expr += "\n%s" % (user_return_code,)
174ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton
175ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    return expr
1760d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton
1770d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Claytondef get_member_types_for_offset(value_type, offset, member_list):
1780d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton    member = value_type.GetFieldAtIndex(0)
1790d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton    search_bases = False
1800d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton    if member:
1810d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton        if member.GetOffsetInBytes() <= offset:
1820d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            for field_idx in range (value_type.GetNumberOfFields()):
1830d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                member = value_type.GetFieldAtIndex(field_idx)
1840d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                member_byte_offset = member.GetOffsetInBytes()
1850d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                member_end_byte_offset = member_byte_offset + member.type.size
1860d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                if member_byte_offset <= offset and offset < member_end_byte_offset:
1870d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                    member_list.append(member)
1880d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                    get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
1890d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                    return
1900d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton        else:
1910d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            search_bases = True
1920d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton    else:
1930d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton        search_bases = True
1940d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton    if search_bases:
1950d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton        for field_idx in range (value_type.GetNumberOfDirectBaseClasses()):
1960d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member = value_type.GetDirectBaseClassAtIndex(field_idx)
1970d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member_byte_offset = member.GetOffsetInBytes()
1980d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member_end_byte_offset = member_byte_offset + member.type.size
1990d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            if member_byte_offset <= offset and offset < member_end_byte_offset:
2000d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                member_list.append(member)
2010d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
2020d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                return
2030d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton        for field_idx in range (value_type.GetNumberOfVirtualBaseClasses()):
2040d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member = value_type.GetVirtualBaseClassAtIndex(field_idx)
2050d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member_byte_offset = member.GetOffsetInBytes()
2060d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            member_end_byte_offset = member_byte_offset + member.type.size
2070d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton            if member_byte_offset <= offset and offset < member_end_byte_offset:
2080d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                member_list.append(member)
2090d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
2100d0f56d5b81afb0f3d2e71c53947658a4c667f35Greg Clayton                return
2114c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton
2124c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Claytondef append_regex_callback(option, opt, value, parser):
2134c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    try:
2144c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        ivar_regex = re.compile(value)
2154c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        parser.values.ivar_regex_blacklist.append(ivar_regex)
2164c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    except:
2174c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
2189098fee45dc61264a9fe54d075751e76f7de610fGreg Clayton
21993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Claytondef add_common_options(parser):
22093e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
2214c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    parser.add_option('-t', '--type', action='store_true', dest='print_type', help='print the full value of the type for each matching malloc block', default=False)
22293e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
223a936c6e5b2fa2e63939e6cfcd5cf05c6733ae0c0Greg Clayton    parser.add_option('-z', '--size', action='store_true', dest='show_size', help='print the allocation size in bytes', default=False)
224a936c6e5b2fa2e63939e6cfcd5cf05c6733ae0c0Greg Clayton    parser.add_option('-r', '--range', action='store_true', dest='show_range', help='print the allocation address range instead of just the allocation base address', default=False)
22593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
22693e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
2274c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    parser.add_option('-I', '--omit-ivar-regex', type='string', action='callback', callback=append_regex_callback, dest='ivar_regex_blacklist', default=[], help='specify one or more regular expressions used to backlist any matches that are in ivars')
2289098fee45dc61264a9fe54d075751e76f7de610fGreg 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)
2297a24576ff8141db67c52d999c14e474f5bd59f52Greg 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)
230849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser.add_option('-F', '--max-frames', type='int', dest='max_frames', help='the maximum number of stack frames to print when using the --stack or --stack-history options (default=128)', default=128)
231849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser.add_option('-H', '--max-history', type='int', dest='max_history', help='the maximum number of stack history backtraces to print for each allocation when using the --stack-history option (default=16)', default=16)
232549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=32)
233ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton    parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1)
234ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    parser.add_option('--ignore-stack', action='store_false', dest='search_stack', help="Don't search the stack when enumerating memory", default=True)
235ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    parser.add_option('--ignore-heap', action='store_false', dest='search_heap', help="Don't search the heap allocations when enumerating memory", default=True)
236ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    parser.add_option('--ignore-segments', action='store_false', dest='search_segments', help="Don't search readable executable segments enumerating memory", default=True)
237ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    parser.add_option('-V', '--vm-regions', action='store_true', dest='search_vm_regions', help='Check all VM regions instead of searching the heap, stack and segments', default=False)
2387a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton
239849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef type_flags_to_string(type_flags):
240849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if type_flags == 0:
241849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'free'
242849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 2:
243849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'malloc'
244849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 4:
245849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'free'
246849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 1:
247849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'generic'
248849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 8:
249849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'stack'
250549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    elif type_flags & 16:
251ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        type_str = 'stack (red zone)'
252ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    elif type_flags & 32:
253549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str = 'segment'
254ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    elif type_flags & 64:
255ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        type_str = 'vm_region'
256849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
257849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = hex(type_flags)
258849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return type_str
259849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
260549294a273c684afbc3227a02119bbbce79fd810Greg Claytondef type_flags_to_description(type_flags, ptr_addr, ptr_size, offset):
261549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    show_offset = False
262849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if type_flags == 0 or type_flags & 4:
263849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = 'free(%#x)' % (ptr_addr,)
264849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 2 or type_flags & 1:
265549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str = 'malloc(%6u) -> %#x' % (ptr_size, ptr_addr)
266549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        show_offset = True
267849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    elif type_flags & 8:
268549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str = 'stack'
269549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    elif type_flags & 16:
270ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        type_str = 'stack (red zone)'
271ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    elif type_flags & 32:
272549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        sb_addr = lldb.debugger.GetSelectedTarget().ResolveLoadAddress(ptr_addr + offset)
273549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str = 'segment [%#x - %#x), %s + %u, %s' % (ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr)
274ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    elif type_flags & 64:
275ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        sb_addr = lldb.debugger.GetSelectedTarget().ResolveLoadAddress(ptr_addr + offset)
276ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        type_str = 'vm_region [%#x - %#x), %s + %u, %s' % (ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr)
277849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
278549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str = '%#x' % (ptr_addr,)
279549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        show_offset = True
280549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if show_offset and offset != 0:
281549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        type_str += ' + %-6u' % (offset,)
282849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return type_str
283849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
284849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef dump_stack_history_entry(options, result, stack_history_entry, idx):
2856f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton    address = int(stack_history_entry.address)
2866f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton    if address:
2876f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton        type_flags = int(stack_history_entry.type_flags)
2887a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton        symbolicator = lldb.utils.symbolication.Symbolicator()
289849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        symbolicator.target = lldb.debugger.GetSelectedTarget()
290849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        type_str = type_flags_to_string(type_flags)
29185df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton        result.AppendMessage('stack[%u]: addr = 0x%x, type=%s, frames:' % (idx, address, type_str))
2927a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton        frame_idx = 0
2936f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton        idx = 0
2946f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton        pc = int(stack_history_entry.frames[idx])
2957a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton        while pc != 0:
2967a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton            if pc >= 0x1000:
2977a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                frames = symbolicator.symbolicate(pc)
2987a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                if frames:
2997a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                    for frame in frames:
30085df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton                        result.AppendMessage('     [%u] %s' % (frame_idx, frame))
3017a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                        frame_idx += 1
3027a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                else:
30385df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton                    result.AppendMessage('     [%u] 0x%x' % (frame_idx, pc))
3047a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                    frame_idx += 1
3056f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton                idx = idx + 1
3066f446f30e47824cabecc22ee3ec68b9450e39c4cGreg Clayton                pc = int(stack_history_entry.frames[idx])
3077a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton            else:
3087a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton                pc = 0
309849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if idx >= options.max_frames:
310849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            result.AppendMessage('warning: the max number of stack frames (%u) was reached, use the "--max-frames=<COUNT>" option to see more frames' % (options.max_frames))
311849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
31285df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton        result.AppendMessage('')
3137a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton
314849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef dump_stack_history_entries(options, result, addr, history):
3157a24576ff8141db67c52d999c14e474f5bd59f52Greg Clayton    # malloc_stack_entry *get_stack_history_for_address (const void * addr)
316549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    single_expr = '''
317549294a273c684afbc3227a02119bbbce79fd810Greg Claytontypedef int kern_return_t;
318849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton#define MAX_FRAMES %u
319849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct $malloc_stack_entry {
320849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t address;
321849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t argument;
322849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint32_t type_flags;
323849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint32_t num_frames;
324849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t frames[512];
325849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    kern_return_t err;
326849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} $malloc_stack_entry;
327849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef unsigned task_t;
328849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton$malloc_stack_entry stack;
329849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack.address = 0x%x;
330849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack.type_flags = 2;
331849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack.num_frames = 0;
332849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack.frames[0] = 0;
333849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonuint32_t max_stack_frames = MAX_FRAMES;
334849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack.err = (kern_return_t)__mach_stack_logging_get_frames (
335849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    (task_t)mach_task_self(),
336849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    stack.address,
337849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    &stack.frames[0],
338849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    max_stack_frames,
339849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    &stack.num_frames);
340849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonif (stack.num_frames < MAX_FRAMES)
341849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    stack.frames[stack.num_frames] = 0;
342849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonelse
343849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    stack.frames[MAX_FRAMES-1] = 0;
344849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstack''' % (options.max_frames, addr);
345849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
346549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    history_expr = '''
347549294a273c684afbc3227a02119bbbce79fd810Greg Claytontypedef int kern_return_t;
348849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef unsigned task_t;
349849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton#define MAX_FRAMES %u
350849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton#define MAX_HISTORY %u
351849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct mach_stack_logging_record_t {
352849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton	uint32_t type_flags;
353849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton	uint64_t stack_identifier;
354849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton	uint64_t argument;
355849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton	uint64_t address;
356849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} mach_stack_logging_record_t;
357849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef void (*enumerate_callback_t)(mach_stack_logging_record_t, void *);
358849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct malloc_stack_entry {
359849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t address;
360849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t argument;
361849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint32_t type_flags;
362849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint32_t num_frames;
363849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uint64_t frames[MAX_FRAMES];
364849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    kern_return_t frames_err;
365849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} malloc_stack_entry;
366849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct $malloc_stack_history {
367849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    task_t task;
368849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned idx;
369849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    malloc_stack_entry entries[MAX_HISTORY];
370849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} $malloc_stack_history;
371849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton$malloc_stack_history info = { (task_t)mach_task_self(), 0 };
372849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonuint32_t max_stack_frames = MAX_FRAMES;
373849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonenumerate_callback_t callback = [] (mach_stack_logging_record_t stack_record, void *baton) -> void {
374849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    $malloc_stack_history *info = ($malloc_stack_history *)baton;
375849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if (info->idx < MAX_HISTORY) {
376849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        malloc_stack_entry *stack_entry = &(info->entries[info->idx]);
377849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->address = stack_record.address;
378849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->type_flags = stack_record.type_flags;
379849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->argument = stack_record.argument;
380849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->num_frames = 0;
381849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->frames[0] = 0;
382849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        stack_entry->frames_err = (kern_return_t)__mach_stack_logging_frames_for_uniqued_stack (
383849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->task,
384849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            stack_record.stack_identifier,
385849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            stack_entry->frames,
386849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            (uint32_t)MAX_FRAMES,
387849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            &stack_entry->num_frames);
388849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        // Terminate the frames with zero if there is room
389849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if (stack_entry->num_frames < MAX_FRAMES)
390849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            stack_entry->frames[stack_entry->num_frames] = 0;
391849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
392849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    ++info->idx;
393849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
394849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton(kern_return_t)__mach_stack_logging_enumerate_records (info.task, (uint64_t)0x%x, callback, &info);
395849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoninfo''' % (options.max_frames, options.max_history, addr);
396849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
397849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
398849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if history:
399849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        expr = history_expr
400849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
401849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        expr = single_expr
4025b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options = lldb.SBExpressionOptions()
4035b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetIgnoreBreakpoints(True);
4045b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTimeoutInMicroSeconds (5*1000*1000) # 5 second timeout
4055b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTryAllThreads (True)
4065b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_sbvalue = frame.EvaluateExpression (expr, expr_options)
407849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if options.verbose:
408849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print "expression:"
409849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print expr
410849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print "expression result:"
411849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print expr_sbvalue
412849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if expr_sbvalue.error.Success():
413849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if history:
414849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            malloc_stack_history = lldb.value(expr_sbvalue)
415849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            num_stacks = int(malloc_stack_history.idx)
416849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if num_stacks <= options.max_history:
417849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                i_max = num_stacks
418849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            else:
419849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                i_max = options.max_history
420849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            for i in range(i_max):
421849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                stack_history_entry = malloc_stack_history.entries[i]
422849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                dump_stack_history_entry(options, result, stack_history_entry, i)
423849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if num_stacks > options.max_history:
424849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                result.AppendMessage('warning: the max number of stacks (%u) was reached, use the "--max-history=%u" option to see all of the stacks' % (options.max_history, num_stacks))
425849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        else:
426849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            stack_history_entry = lldb.value(expr_sbvalue)
427849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            dump_stack_history_entry(options, result, stack_history_entry, 0)
428849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
429849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
430849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: expression failed "%s" => %s' % (expr, expr_sbvalue.error))
431849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
432849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
433849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef display_match_results (result, options, arg_str_description, expr, print_no_matches = True):
434849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
435849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not frame:
436849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: invalid frame')
437849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return 0
4385b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options = lldb.SBExpressionOptions()
4395b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetIgnoreBreakpoints(True);
4405b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetFetchDynamicValue(lldb.eNoDynamicValues);
4415b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTimeoutInMicroSeconds (30*1000*1000) # 30 second timeout
4425b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTryAllThreads (False)
4435b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_sbvalue = frame.EvaluateExpression (expr, expr_options)
444849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if options.verbose:
445849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print "expression:"
446849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print expr
447849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print "expression result:"
448849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        print expr_sbvalue
4499666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    if expr_sbvalue.error.Success():
4509666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        if expr_sbvalue.unsigned:
4519666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            match_value = lldb.value(expr_sbvalue)
4529666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            i = 0
453ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton            match_idx = 0
4549666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton            while 1:
4554c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                print_entry = True
4569666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                match_entry = match_value[i]; i += 1
457849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                if i > options.max_matches:
458849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    result.AppendMessage('warning: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches))
4594c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    break
4609666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                malloc_addr = match_entry.addr.sbvalue.unsigned
4619666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                if malloc_addr == 0:
4629666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                    break
4639666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                malloc_size = int(match_entry.size)
4649666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton                offset = int(match_entry.offset)
465ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton
466ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                if options.offset >= 0 and options.offset != offset:
467ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                    print_entry = False
468ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                else:
469ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                    match_addr = malloc_addr + offset
470849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    type_flags = int(match_entry.type)
471ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                    #result.AppendMessage (hex(malloc_addr + offset))
472ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                    if type_flags == 64:
473ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        search_stack_old = options.search_stack
474ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        search_segments_old = options.search_segments
475ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        search_heap_old = options.search_heap
476ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        search_vm_regions = options.search_vm_regions
477ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_stack = True
478ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_segments = True
479ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_heap = True
480ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_vm_regions = False
481ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        if malloc_info_impl (lldb.debugger, result, options, [hex(malloc_addr + offset)]):
482ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            print_entry = False
483ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_stack = search_stack_old
484ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_segments = search_segments_old
485ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_heap = search_heap_old
486ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        options.search_vm_regions = search_vm_regions
487ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                    if print_entry:
488ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        description = '%#16.16x: %s' % (match_addr, type_flags_to_description(type_flags, malloc_addr, malloc_size, offset))
489ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        if options.show_size:
490ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            description += ' <%5u>' % (malloc_size)
491ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        if options.show_range:
492ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            description += ' [%#x - %#x)' % (malloc_addr, malloc_addr + malloc_size)
493ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        derefed_dynamic_value = None
494ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
495ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                        if dynamic_value.type.name == 'void *':
496ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            if options.type == 'pointer' and malloc_size == 4096:
497ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                error = lldb.SBError()
498ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                process = expr_sbvalue.GetProcess()
499ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                target = expr_sbvalue.GetTarget()
500ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                data = bytearray(process.ReadMemory(malloc_addr, 16, error))
501ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
502ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    ptr_size = target.addr_size
503ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    thread = process.ReadUnsignedFromMemory (malloc_addr + 16 + ptr_size, ptr_size, error)
504ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    #   4 bytes  0xa1a1a1a1
505ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    #  12 bytes  'AUTORELEASE!'
506ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    # ptr bytes  autorelease insertion point
507ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    # ptr bytes  pthread_t
508ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    # ptr bytes  next colder page
509ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    # ptr bytes  next hotter page
510ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    #   4 bytes  this page's depth in the list
511ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    #   4 bytes  high-water mark
512ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    description += ' AUTORELEASE! for pthread_t %#x' % (thread)
513ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            #     else:
514ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            #         description += 'malloc(%u)' % (malloc_size)
515ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            # else:
516ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            #     description += 'malloc(%u)' % (malloc_size)
517a936c6e5b2fa2e63939e6cfcd5cf05c6733ae0c0Greg Clayton                        else:
518ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            derefed_dynamic_value = dynamic_value.deref
519ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            if derefed_dynamic_value:
520ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                derefed_dynamic_type = derefed_dynamic_value.type
521ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                derefed_dynamic_type_size = derefed_dynamic_type.size
522ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                derefed_dynamic_type_name = derefed_dynamic_type.name
523ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                description += ' '
524ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                description += derefed_dynamic_type_name
525ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                if offset < derefed_dynamic_type_size:
526ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    member_list = list();
527ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
528ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    if member_list:
529ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                        member_path = ''
530ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                        for member in member_list:
531ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                            member_name = member.name
532ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                            if member_name:
533ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                if member_path:
534ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                    member_path += '.'
535ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                member_path += member_name
536ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                        if member_path:
537ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                            if options.ivar_regex_blacklist:
538ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                for ivar_regex in options.ivar_regex_blacklist:
539ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                    if ivar_regex.match(member_path):
540ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                                        print_entry = False
541ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                            description += '.%s' % (member_path)
542ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                else:
543ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                    description += '%u bytes after %s' % (offset - derefed_dynamic_type_size, derefed_dynamic_type_name)
544ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                            else:
545ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                # strip the "*" from the end of the name since we were unable to dereference this
546ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                                description += dynamic_value.type.name[0:-1]
5474c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                if print_entry:
548ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                    match_idx += 1
549aaf7fad2bb839010596e6d8e673e9635f4ddf372Greg Clayton                    result_output = ''
5504c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    if description:
551aaf7fad2bb839010596e6d8e673e9635f4ddf372Greg Clayton                        result_output += description
5524c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        if options.print_type and derefed_dynamic_value:
553549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                            result_output += ' %s' % (derefed_dynamic_value)
5544c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        if options.print_object_description and dynamic_value:
5554c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                            desc = dynamic_value.GetObjectDescription()
5564c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                            if desc:
557a936c6e5b2fa2e63939e6cfcd5cf05c6733ae0c0Greg Clayton                                result_output += '\n%s' % (desc)
558aaf7fad2bb839010596e6d8e673e9635f4ddf372Greg Clayton                    if result_output:
559aaf7fad2bb839010596e6d8e673e9635f4ddf372Greg Clayton                        result.AppendMessage(result_output)
5604c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    if options.memory:
5614c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        cmd_result = lldb.SBCommandReturnObject()
562849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        if options.format == None:
563849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                            memory_command = "memory read --force 0x%x 0x%x" % (malloc_addr, malloc_addr + malloc_size)
564849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        else:
565849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                            memory_command = "memory read --force -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
566849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        if options.verbose:
567849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                            result.AppendMessage(memory_command)
5684c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
56985df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton                        result.AppendMessage(cmd_result.GetOutput())
5704c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    if options.stack_history:
571549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                        dump_stack_history_entries(options, result, malloc_addr, 1)
5724c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    elif options.stack:
573549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                        dump_stack_history_entries(options, result, malloc_addr, 0)
5744c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton            return i
5754c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        elif print_no_matches:
57685df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton            result.AppendMessage('no matches found for %s' % (arg_str_description))
5779666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    else:
578aaf7fad2bb839010596e6d8e673e9635f4ddf372Greg Clayton        result.AppendMessage(str(expr_sbvalue.error))
5794c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    return 0
5804c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton
581849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef get_ptr_refs_options ():
582bf4796585224db7256f5c0df8bab22b304f4615eGreg Clayton    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
583849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    description='''Searches all allocations on the heap for pointer values on
584849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondarwin user space programs. Any matches that were found will dump the malloc
585849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonblocks that contain the pointers and might be able to print what kind of
586849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonobjects the pointers are contained in using dynamic type information in the
587849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonprogram.'''
588bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    parser = optparse.OptionParser(description=description, prog='ptr_refs',usage=usage)
58993e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
590849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return parser
591849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
592849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef ptr_refs(debugger, command, result, dict):
593849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    command_args = shlex.split(command)
594849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = get_ptr_refs_options()
595e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    try:
596e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton        (options, args) = parser.parse_args(command_args)
597e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    except:
598e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton        return
5999666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
600849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    process = lldb.debugger.GetSelectedTarget().GetProcess()
601849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not process:
602849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: invalid process')
603849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
604849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    frame = process.GetSelectedThread().GetSelectedFrame()
605849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not frame:
606849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: invalid frame')
607849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
608849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
6099666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    options.type = 'pointer'
610849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if options.format == None:
611849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        options.format = "A" # 'A' is "address" format
612849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
613e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    if args:
614849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # When we initialize the expression, we must define any types that
615849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # we will need when looking at every allocation. We must also define
616849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a type named callback_baton_t and make an instance named "baton"
617849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and initialize it how ever we want to. The address of "baton" will
618849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # be passed into our range callback. callback_baton_t must contain
619849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a member named "callback" whose type is "range_callback_t". This
620849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # will be used by our zone callbacks to call the range callback for
621849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # each malloc range.
622549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        user_init_code_format = '''
623549294a273c684afbc3227a02119bbbce79fd810Greg Clayton#define MAX_MATCHES %u
624849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstruct $malloc_match {
625849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *addr;
626849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t size;
627849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t offset;
628849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t type;
629849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
630849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct callback_baton_t {
631849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    range_callback_t callback;
632849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned num_matches;
633549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    $malloc_match matches[MAX_MATCHES];
634849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *ptr;
635849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} callback_baton_t;
636849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonrange_callback_t range_callback = [](task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size) -> void {
637849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    callback_baton_t *info = (callback_baton_t *)baton;
638849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    typedef void* T;
639849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    const unsigned size = sizeof(T);
640849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    T *array = (T*)ptr_addr;
641849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    for (unsigned idx = 0; ((idx + 1) * sizeof(T)) <= ptr_size; ++idx) {
642849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if (array[idx] == info->ptr) {
643549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            if (info->num_matches < MAX_MATCHES) {
644849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                info->matches[info->num_matches].addr = (void*)ptr_addr;
645849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                info->matches[info->num_matches].size = ptr_size;
646849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                info->matches[info->num_matches].offset = idx*sizeof(T);
647849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                info->matches[info->num_matches].type = type;
648849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                ++info->num_matches;
649849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            }
650849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        }
651849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
652849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
653849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncallback_baton_t baton = { range_callback, 0, {0}, (void *)%s };
654849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton'''
655849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # We must also define a snippet of code to be run that returns
656849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the result of the expression we run.
657849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Here we return NULL if our pointer was not found in any malloc blocks,
658849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and we return the address of the matches array so we can then access
659849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the matching results
660549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        user_return_code = '''if (baton.num_matches < MAX_MATCHES)
661549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
662849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonbaton.matches'''
663849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Iterate through all of our pointer expressions and display the results
664849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for ptr_expr in args:
665549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            user_init_code = user_init_code_format % (options.max_matches, ptr_expr)
666ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code)
667849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            arg_str_description = 'malloc block containing pointer %s' % ptr_expr
668849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            display_match_results (result, options, arg_str_description, expr)
669e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton    else:
670849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: no pointer arguments were given')
6719666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
672849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef get_cstr_refs_options():
673bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    usage = "usage: %prog [options] <CSTR> [CSTR ...]"
674849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    description='''Searches all allocations on the heap for C string values on
675849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondarwin user space programs. Any matches that were found will dump the malloc
676849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonblocks that contain the C strings and might be able to print what kind of
677849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonobjects the pointers are contained in using dynamic type information in the
678849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonprogram.'''
679bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
68093e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
681849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return parser
682849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
683849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef cstr_refs(debugger, command, result, dict):
684849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    command_args = shlex.split(command)
685849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = get_cstr_refs_options();
6869666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    try:
6879666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        (options, args) = parser.parse_args(command_args)
6889666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    except:
6899666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton        return
6909666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton
691549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    process = lldb.debugger.GetSelectedTarget().GetProcess()
692549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if not process:
693549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result.AppendMessage('error: invalid process')
694549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return
695549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    frame = process.GetSelectedThread().GetSelectedFrame()
696849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not frame:
697849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: invalid frame')
698849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
699849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
700549294a273c684afbc3227a02119bbbce79fd810Greg Clayton
7019666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    options.type = 'cstr'
702849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if options.format == None:
703849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        options.format = "Y" # 'Y' is "bytes with ASCII" format
704e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
7059666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    if args:
706849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # When we initialize the expression, we must define any types that
707849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # we will need when looking at every allocation. We must also define
708849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a type named callback_baton_t and make an instance named "baton"
709849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and initialize it how ever we want to. The address of "baton" will
710849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # be passed into our range callback. callback_baton_t must contain
711849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a member named "callback" whose type is "range_callback_t". This
712849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # will be used by our zone callbacks to call the range callback for
713849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # each malloc range.
714549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        user_init_code_format = '''
715549294a273c684afbc3227a02119bbbce79fd810Greg Clayton#define MAX_MATCHES %u
716549294a273c684afbc3227a02119bbbce79fd810Greg Claytonstruct $malloc_match {
717849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *addr;
718849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t size;
719849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t offset;
720849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t type;
721849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
722849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct callback_baton_t {
723849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    range_callback_t callback;
724849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned num_matches;
725549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    $malloc_match matches[MAX_MATCHES];
726849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    const char *cstr;
727849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned cstr_len;
728849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} callback_baton_t;
729849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonrange_callback_t range_callback = [](task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size) -> void {
730849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    callback_baton_t *info = (callback_baton_t *)baton;
731849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if (info->cstr_len < ptr_size) {
732849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        const char *begin = (const char *)ptr_addr;
733849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        const char *end = begin + ptr_size - info->cstr_len;
734849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for (const char *s = begin; s < end; ++s) {
735849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if ((int)memcmp(s, info->cstr, info->cstr_len) == 0) {
736549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                if (info->num_matches < MAX_MATCHES) {
737849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].addr = (void*)ptr_addr;
738849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].size = ptr_size;
739849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].offset = s - begin;
740849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].type = type;
741849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    ++info->num_matches;
742849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                }
743849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            }
744849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        }
745849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
746849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
747849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonconst char *cstr = "%s";
748849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncallback_baton_t baton = { range_callback, 0, {0}, cstr, (unsigned)strlen(cstr) };'''
749849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # We must also define a snippet of code to be run that returns
750849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the result of the expression we run.
751849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Here we return NULL if our pointer was not found in any malloc blocks,
752849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and we return the address of the matches array so we can then access
753849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the matching results
754549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        user_return_code = '''if (baton.num_matches < MAX_MATCHES)
755549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
756549294a273c684afbc3227a02119bbbce79fd810Greg Claytonbaton.matches'''
757849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Iterate through all of our pointer expressions and display the results
758849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for cstr in args:
759549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            user_init_code = user_init_code_format % (options.max_matches, cstr)
760ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code)
761849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            arg_str_description = 'malloc block containing "%s"' % cstr
762849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            display_match_results (result, options, arg_str_description, expr)
7639666644d2b0da00eb0792f4de6f5b3cb98ac5fa0Greg Clayton    else:
764849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: command takes one or more C string arguments')
765e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
766bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
767849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef get_malloc_info_options():
768849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
769849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    description='''Searches the heap a malloc block that contains the addresses
770849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonspecified as one or more address expressions. Any matches that were found will
771849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondump the malloc blocks that match or contain the specified address. The matching
772849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonblocks might be able to show what kind of objects they are using dynamic type
773849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoninformation in the program.'''
774849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = optparse.OptionParser(description=description, prog='malloc_info',usage=usage)
77593e5ba5ec34531a68b2d3bc82c3bcb2aa8d22032Greg Clayton    add_common_options(parser)
776849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return parser
777849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
778849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef malloc_info(debugger, command, result, dict):
779849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    command_args = shlex.split(command)
780849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = get_malloc_info_options()
781bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    try:
782bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        (options, args) = parser.parse_args(command_args)
783bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    except:
784bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton        return
785ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    malloc_info_impl (debugger, result, options, args)
786ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton
787ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytondef malloc_info_impl (debugger, result, options, args):
788ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    # We are specifically looking for something on the heap only
789ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton    options.type = 'malloc_info'
790549294a273c684afbc3227a02119bbbce79fd810Greg Clayton
791549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    process = lldb.debugger.GetSelectedTarget().GetProcess()
792549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if not process:
793549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result.AppendMessage('error: invalid process')
794549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return
795549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    frame = process.GetSelectedThread().GetSelectedFrame()
796549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if not frame:
797549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result.AppendMessage('error: invalid frame')
798549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return
799849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
800549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    user_init_code_format = '''
801549294a273c684afbc3227a02119bbbce79fd810Greg Claytonstruct $malloc_match {
802849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *addr;
803849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t size;
804849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t offset;
805849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t type;
806849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
807849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct callback_baton_t {
808849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    range_callback_t callback;
809849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned num_matches;
810849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    $malloc_match matches[2]; // Two items so they can be NULL terminated
811849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *ptr;
812849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} callback_baton_t;
813849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonrange_callback_t range_callback = [](task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size) -> void {
814849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    callback_baton_t *info = (callback_baton_t *)baton;
815849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if (info->num_matches == 0) {
816849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        uint8_t *p = (uint8_t *)info->ptr;
817849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        uint8_t *lo = (uint8_t *)ptr_addr;
818849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        uint8_t *hi = lo + ptr_size;
819849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if (lo <= p && p < hi) {
820849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->matches[info->num_matches].addr = (void*)ptr_addr;
821849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->matches[info->num_matches].size = ptr_size;
822849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->matches[info->num_matches].offset = p - lo;
823849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->matches[info->num_matches].type = type;
824849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            info->num_matches = 1;
825849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        }
826849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
827849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
828849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncallback_baton_t baton = { range_callback, 0, {0}, (void *)%s };
829549294a273c684afbc3227a02119bbbce79fd810Greg Claytonbaton.matches[0].addr = 0;
830849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonbaton.matches[1].addr = 0;'''
831bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    if args:
832ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        total_matches = 0
833549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        for ptr_expr in args:
834549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            user_init_code = user_init_code_format % (ptr_expr)
835ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            expr = get_iterate_memory_expr(options, process, user_init_code, 'baton.matches')
836549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            arg_str_description = 'malloc block that contains %s' % ptr_expr
837ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton            total_matches += display_match_results (result, options, arg_str_description, expr)
838ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        return total_matches
839bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton    else:
840849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: command takes one or more pointer expressions')
841ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        return 0
842bff78410b94d0b52956e3c6f2966b25a9b799366Greg Clayton
843849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef get_thread_stack_ranges_struct (process):
844549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    '''Create code that defines a structure that represents threads stack bounds
845549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    for all  threads. It returns a static sized array initialized with all of
846549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    the tid, base, size structs for all the threads.'''
847849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    stack_dicts = list()
848849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if process:
849849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        i = 0;
850849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for thread in process:
851849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            min_sp = thread.frame[0].sp
852849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            max_sp = min_sp
853849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            for frame in thread.frames:
854849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                sp = frame.sp
855849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                if sp < min_sp: min_sp = sp
856849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                if sp > max_sp: max_sp = sp
857849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if min_sp < max_sp:
858849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                stack_dicts.append ({ 'tid' : thread.GetThreadID(), 'base' : min_sp  , 'size' : max_sp-min_sp, 'index' : i })
859849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                i += 1
860849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    stack_dicts_len = len(stack_dicts)
861849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if stack_dicts_len > 0:
862549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result = '''
863549294a273c684afbc3227a02119bbbce79fd810Greg Clayton#define NUM_STACKS %u
864ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define STACK_RED_ZONE_SIZE %u
865849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct thread_stack_t { uint64_t tid, base, size; } thread_stack_t;
866ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Claytonthread_stack_t stacks[NUM_STACKS];''' % (stack_dicts_len, process.target.GetStackRedZoneSize())
867849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for stack_dict in stack_dicts:
868549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            result += '''
869549294a273c684afbc3227a02119bbbce79fd810Greg Claytonstacks[%(index)u].tid  = 0x%(tid)x;
870849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonstacks[%(index)u].base = 0x%(base)x;
871549294a273c684afbc3227a02119bbbce79fd810Greg Claytonstacks[%(index)u].size = 0x%(size)x;''' % stack_dict
872849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return result
873849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
874849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return None
875130a3127926fe704f9d5e0552e873505c6c10313Greg Clayton
876549294a273c684afbc3227a02119bbbce79fd810Greg Claytondef get_sections_ranges_struct (process):
877549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    '''Create code that defines a structure that represents all segments that
878549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    can contain data for all images in "target". It returns a static sized
879549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    array initialized with all of base, size structs for all the threads.'''
880549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    target = process.target
881549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    segment_dicts = list()
882549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    for (module_idx, module) in enumerate(target.modules):
883549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        for sect_idx in range(module.GetNumSections()):
884549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            section = module.GetSectionAtIndex(sect_idx)
885549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            if not section:
886549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                break
887549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            name = section.name
888549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            if name != '__TEXT' and name != '__LINKEDIT' and name != '__PAGEZERO':
889549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                base = section.GetLoadAddress(target)
890549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                size = section.GetByteSize()
891549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                if base != lldb.LLDB_INVALID_ADDRESS and size > 0:
892549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                    segment_dicts.append ({ 'base' : base, 'size' : size })
893549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    segment_dicts_len = len(segment_dicts)
894549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if segment_dicts_len > 0:
895549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result = '''
896549294a273c684afbc3227a02119bbbce79fd810Greg Clayton#define NUM_SEGMENTS %u
897549294a273c684afbc3227a02119bbbce79fd810Greg Claytontypedef struct segment_range_t { uint64_t base; uint32_t size; } segment_range_t;
898549294a273c684afbc3227a02119bbbce79fd810Greg Claytonsegment_range_t segments[NUM_SEGMENTS];''' % (segment_dicts_len,)
899549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        for (idx, segment_dict) in enumerate(segment_dicts):
900549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            segment_dict['index'] = idx
901549294a273c684afbc3227a02119bbbce79fd810Greg Clayton            result += '''
902549294a273c684afbc3227a02119bbbce79fd810Greg Claytonsegments[%(index)u].base = 0x%(base)x;
903549294a273c684afbc3227a02119bbbce79fd810Greg Claytonsegments[%(index)u].size = 0x%(size)x;''' % segment_dict
904549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return result
905130a3127926fe704f9d5e0552e873505c6c10313Greg Clayton    else:
906549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return None
907130a3127926fe704f9d5e0552e873505c6c10313Greg Clayton
9084c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Claytondef section_ptr_refs(debugger, command, result, dict):
9094c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    command_args = shlex.split(command)
9104c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
9114c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    description='''Searches section contents for pointer values in darwin user space programs.'''
9124c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage)
9134c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    add_common_options(parser)
9144c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list())
9154c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    try:
9164c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        (options, args) = parser.parse_args(command_args)
9174c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    except:
9184c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        return
9194c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton
9204c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    options.type = 'pointer'
921130a3127926fe704f9d5e0552e873505c6c10313Greg Clayton
9224c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    sections = list()
9234c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    section_modules = list()
9244c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    if not options.section_names:
92585df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton        result.AppendMessage('error: at least one section must be specified with the --section option')
9264c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        return
9274c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton
928849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    target = lldb.debugger.GetSelectedTarget()
929849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    for module in target.modules:
9304c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        for section_name in options.section_names:
9314c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton            section = module.section[section_name]
9324c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton            if section:
9334c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                sections.append (section)
9344c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                section_modules.append (module)
9354c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    if sections:
9364c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        dylid_load_err = load_dylib()
9374c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        if dylid_load_err:
93885df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton            result.AppendMessage(dylid_load_err)
9394c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton            return
940849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        frame = target.GetProcess().GetSelectedThread().GetSelectedFrame()
9414c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton        for expr_str in args:
9424c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton            for (idx, section) in enumerate(sections):
9434c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str)
9444c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str)
945849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                num_matches = display_match_results (result, options, arg_str_description, expr, False)
9464c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                if num_matches:
9474c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    if num_matches < options.max_matches:
9484c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        options.max_matches = options.max_matches - num_matches
9494c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    else:
9504c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                        options.max_matches = 0
9514c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                if options.max_matches == 0:
9524c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton                    return
9534c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton    else:
95485df60cecb0d0d2d223ef613f998dc2a9ff1b3e7Greg Clayton        result.AppendMessage('error: no sections were found that match any of %s' % (', '.join(options.section_names)))
9554c5c429b0cd53a4df9f0fab3482e73aa71fc5b91Greg Clayton
956849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytondef get_objc_refs_options():
957849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    usage = "usage: %prog [options] <CLASS> [CLASS ...]"
958849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    description='''Searches all allocations on the heap for instances of
959849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonobjective C classes, or any classes that inherit from the specified classes
960849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonin darwin user space programs. Any matches that were found will dump the malloc
961849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonblocks that contain the C strings and might be able to print what kind of
962849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonobjects the pointers are contained in using dynamic type information in the
963849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonprogram.'''
964849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = optparse.OptionParser(description=description, prog='objc_refs',usage=usage)
965849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    add_common_options(parser)
966849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    return parser
967849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
968ab20f29e71457e73c2542b763c1ff2d529d21399Greg Claytondef objc_refs(debugger, command, result, dict):
969ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton    command_args = shlex.split(command)
970849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    parser = get_objc_refs_options()
971ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton    try:
972ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton        (options, args) = parser.parse_args(command_args)
973ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton    except:
974ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton        return
975ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton
976549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    process = lldb.debugger.GetSelectedTarget().GetProcess()
977549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    if not process:
978549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        result.AppendMessage('error: invalid process')
979549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        return
980549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    frame = process.GetSelectedThread().GetSelectedFrame()
981849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not frame:
982849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: invalid frame')
983849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
984849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
985849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    options.type = 'isa'
986849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if options.format == None:
987849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        options.format = "A" # 'A' is "address" format
988849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
9895b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options = lldb.SBExpressionOptions()
9905b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetIgnoreBreakpoints(True);
9915b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTimeoutInMicroSeconds (3*1000*1000) # 3 second infinite timeout
9925b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    expr_options.SetTryAllThreads (True)
9935b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton    num_objc_classes_value = frame.EvaluateExpression("(int)objc_getClassList((void *)0, (int)0)", expr_options)
994849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if not num_objc_classes_value.error.Success():
995849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: %s' % num_objc_classes_value.error.GetCString())
996849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
997849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
998849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    num_objc_classes = num_objc_classes_value.GetValueAsUnsigned()
999849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if num_objc_classes == 0:
1000849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: no objective C classes in program')
1001849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        return
1002849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton
1003849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if args:
1004849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # When we initialize the expression, we must define any types that
1005849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # we will need when looking at every allocation. We must also define
1006849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a type named callback_baton_t and make an instance named "baton"
1007849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and initialize it how ever we want to. The address of "baton" will
1008849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # be passed into our range callback. callback_baton_t must contain
1009849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # a member named "callback" whose type is "range_callback_t". This
1010849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # will be used by our zone callbacks to call the range callback for
1011849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # each malloc range.
1012ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton        user_init_code_format = '''
1013ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton#define MAX_MATCHES %u
1014549294a273c684afbc3227a02119bbbce79fd810Greg Claytonstruct $malloc_match {
1015849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *addr;
1016849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t size;
1017849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t offset;
1018849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    uintptr_t type;
1019849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
1020849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef int (*compare_callback_t)(const void *a, const void *b);
1021849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytontypedef struct callback_baton_t {
1022849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    range_callback_t callback;
1023849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    compare_callback_t compare_callback;
1024849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    unsigned num_matches;
1025549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    $malloc_match matches[MAX_MATCHES];
1026849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    void *isa;
1027849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    Class classes[%u];
1028849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton} callback_baton_t;
1029849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncompare_callback_t compare_callback = [](const void *a, const void *b) -> int {
1030849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton     Class a_ptr = *(Class *)a;
1031849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton     Class b_ptr = *(Class *)b;
1032849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton     if (a_ptr < b_ptr) return -1;
1033849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton     if (a_ptr > b_ptr) return +1;
1034849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton     return 0;
1035849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
1036849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonrange_callback_t range_callback = [](task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size) -> void {
1037849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    callback_baton_t *info = (callback_baton_t *)baton;
1038849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    if (sizeof(Class) <= ptr_size) {
1039849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        Class *curr_class_ptr = (Class *)ptr_addr;
1040849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        Class *matching_class_ptr = (Class *)bsearch (curr_class_ptr,
1041849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                                      (const void *)info->classes,
1042849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                                      sizeof(info->classes)/sizeof(Class),
1043849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                                      sizeof(Class),
1044849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                                                      info->compare_callback);
1045849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        if (matching_class_ptr) {
1046849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            bool match = false;
1047849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if (info->isa) {
1048849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                Class isa = *curr_class_ptr;
1049849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                if (info->isa == isa)
1050849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    match = true;
1051849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                else { // if (info->objc.match_superclasses) {
1052849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    Class super = (Class)class_getSuperclass(isa);
1053849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    while (super) {
1054849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        if (super == info->isa) {
1055849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                            match = true;
1056849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                            break;
1057849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        }
1058849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                        super = (Class)class_getSuperclass(super);
1059849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    }
1060849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                }
1061849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            }
1062849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            else
1063849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                match = true;
1064849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if (match) {
1065549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                if (info->num_matches < MAX_MATCHES) {
1066849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].addr = (void*)ptr_addr;
1067849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].size = ptr_size;
1068849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].offset = 0;
1069849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    info->matches[info->num_matches].type = type;
1070849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    ++info->num_matches;
1071849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                }
1072849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            }
1073849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        }
1074849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    }
1075849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton};
1076849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncallback_baton_t baton = { range_callback, compare_callback, 0, {0}, (void *)0x%x, {0} };
1077849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonint nc = (int)objc_getClassList(baton.classes, sizeof(baton.classes)/sizeof(Class));
1078849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton(void)qsort (baton.classes, sizeof(baton.classes)/sizeof(Class), sizeof(Class), compare_callback);'''
1079849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # We must also define a snippet of code to be run that returns
1080849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the result of the expression we run.
1081849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Here we return NULL if our pointer was not found in any malloc blocks,
1082849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # and we return the address of the matches array so we can then access
1083849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # the matching results
1084549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        user_return_code = '''if (baton.num_matches < MAX_MATCHES)
1085549294a273c684afbc3227a02119bbbce79fd810Greg Clayton    baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
1086549294a273c684afbc3227a02119bbbce79fd810Greg Clayton        baton.matches'''
1087849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        # Iterate through all of our ObjC class name arguments
1088849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        for class_name in args:
1089849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            addr_expr_str = "(void *)[%s class]" % class_name
10905b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton            expr_options = lldb.SBExpressionOptions()
10915b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton            expr_options.SetIgnoreBreakpoints(True);
10925b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton            expr_options.SetTimeoutInMicroSeconds (1*1000*1000) # 1 second timeout
10935b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton            expr_options.SetTryAllThreads (True)
10945b578232a39b8c64c39426ad57b7014ff9ace41bGreg Clayton            expr_sbvalue = frame.EvaluateExpression (addr_expr_str, expr_options)
1095849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            if expr_sbvalue.error.Success():
1096849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                isa = expr_sbvalue.unsigned
1097849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                if isa:
1098849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    options.type = 'isa'
1099549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                    result.AppendMessage('Searching for all instances of classes or subclasses of "%s" (isa=0x%x)' % (class_name, isa))
1100549294a273c684afbc3227a02119bbbce79fd810Greg Clayton                    user_init_code = user_init_code_format % (options.max_matches, num_objc_classes, isa)
1101ad72e52945ee0560fc2b22dce0087d4c7274a218Greg Clayton                    expr = get_iterate_memory_expr(options, process, user_init_code, user_return_code)
1102849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    arg_str_description = 'objective C classes with isa 0x%x' % isa
1103849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    display_match_results (result, options, arg_str_description, expr)
1104ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton                else:
1105849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                    result.AppendMessage('error: Can\'t find isa for an ObjC class named "%s"' % (class_name))
1106849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton            else:
1107849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton                result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error))
1108849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton    else:
1109849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton        result.AppendMessage('error: command takes one or more C string arguments');
1110ab20f29e71457e73c2542b763c1ff2d529d21399Greg Clayton
11111dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Claytonif __name__ == '__main__':
11121dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton    lldb.debugger = lldb.SBDebugger.Create()
11131dae6f39248e38ac84fc20c8b4c26e11bfcc19b7Greg Clayton
1114849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# Make the options so we can generate the help text for the new LLDB
1115849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# command line command prior to registering it with LLDB below. This way
1116849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# if clients in LLDB type "help malloc_info", they will see the exact same
1117849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# output as typing "malloc_info --help".
1118849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonptr_refs.__doc__ = get_ptr_refs_options().format_help()
1119849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytoncstr_refs.__doc__ = get_cstr_refs_options().format_help()
1120849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonmalloc_info.__doc__ = get_malloc_info_options().format_help()
1121849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonobjc_refs.__doc__ = get_objc_refs_options().format_help()
11223801be785a607162d3dda0744a7d915bda4c13a3Enrico Granatalldb.debugger.HandleCommand('command script add -f %s.ptr_refs ptr_refs' % __name__)
11233801be785a607162d3dda0744a7d915bda4c13a3Enrico Granatalldb.debugger.HandleCommand('command script add -f %s.cstr_refs cstr_refs' % __name__)
11243801be785a607162d3dda0744a7d915bda4c13a3Enrico Granatalldb.debugger.HandleCommand('command script add -f %s.malloc_info malloc_info' % __name__)
1125849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# lldb.debugger.HandleCommand('command script add -f %s.heap heap' % package_name)
1126849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# lldb.debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name)
1127849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Clayton# lldb.debugger.HandleCommand('command script add -f %s.stack_ptr_refs stack_ptr_refs' % package_name)
11283801be785a607162d3dda0744a7d915bda4c13a3Enrico Granatalldb.debugger.HandleCommand('command script add -f %s.objc_refs objc_refs' % __name__)
1129849acc83774509a8b67d8a7867b1a8dfc7548e08Greg Claytonprint '"malloc_info", "ptr_refs", "cstr_refs", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
1130e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
1131e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
1132e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
1133e93e24fb12f05cf363bc99e9c792c28cacace0c3Greg Clayton
1134