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