[Lldb-commits] [lldb] r161724 - in /lldb/trunk/examples/darwin/heap_find: heap.py heap/heap_find.cpp

Greg Clayton gclayton at apple.com
Fri Aug 10 19:26:27 PDT 2012


Author: gclayton
Date: Fri Aug 10 21:26:26 2012
New Revision: 161724

URL: http://llvm.org/viewvc/llvm-project?rev=161724&view=rev
Log:
Added a new "objc_refs" command that will track down all allocations on the heap that have the "isa" for the objective C class at offset zero. This will need to be improved to deal with KVO classes, but it is a start. It also disallows looking up a pointer value of zero since that would return way too many matches. 


Modified:
    lldb/trunk/examples/darwin/heap_find/heap.py
    lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp

Modified: lldb/trunk/examples/darwin/heap_find/heap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap.py?rev=161724&r1=161723&r2=161724&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap.py (original)
+++ lldb/trunk/examples/darwin/heap_find/heap.py Fri Aug 10 21:26:26 2012
@@ -131,6 +131,7 @@
     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)
     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)
     parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=256)
+    parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1)
 
 def dump_stack_history_entry(stack_history_entry, idx):
     address = int(stack_history_entry.address)
@@ -192,6 +193,7 @@
         if expr_sbvalue.unsigned:
             match_value = lldb.value(expr_sbvalue)  
             i = 0
+            match_idx = 0
             while 1:
                 print_entry = True
                 match_entry = match_value[i]; i += 1
@@ -203,44 +205,49 @@
                     break
                 malloc_size = int(match_entry.size)
                 offset = int(match_entry.offset)
-                match_addr = malloc_addr + offset
-                dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
-                description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
-                if offset != 0:
-                    description += ' + %u' % (offset)
-                description += ', size = %u' % (malloc_size)
-                derefed_dynamic_value = None
-                if dynamic_value.type.name == 'void *':
-                    if options.type == 'pointer' and malloc_size == 4096:
-                        error = lldb.SBError()
-                        data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
-                        if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
-                            description += ', type = (AUTORELEASE!)'
-                else:
-                    derefed_dynamic_value = dynamic_value.deref
-                    if derefed_dynamic_value:                        
-                        derefed_dynamic_type = derefed_dynamic_value.type
-                        derefed_dynamic_type_size = derefed_dynamic_type.size
-                        derefed_dynamic_type_name = derefed_dynamic_type.name
-                        description += ', type = %s <%u>' % (derefed_dynamic_type_name, derefed_dynamic_type_size)
-                        if offset < derefed_dynamic_type_size:
-                            member_list = list();
-                            get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
-                            if member_list:
-                                member_path = ''
-                                for member in member_list:
-                                    member_name = member.name
-                                    if member_name: 
-                                        if member_path:
-                                            member_path += '.'
-                                        member_path += member_name
-                                if member_path:
-                                    if options.ivar_regex_blacklist:
-                                        for ivar_regex in options.ivar_regex_blacklist:
-                                            if ivar_regex.match(member_path):
-                                                print_entry = False
-                                    description += ', ivar = %s' % (member_path)
+                
+                if options.offset >= 0 and options.offset != offset:
+                    print_entry = False
+                else:                    
+                    match_addr = malloc_addr + offset
+                    dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
+                    description = '[%u] %s: addr = 0x%x' % (match_idx, arg_str_description, malloc_addr)
+                    if offset != 0:
+                        description += ' + %u' % (offset)
+                    description += ', size = %u' % (malloc_size)
+                    derefed_dynamic_value = None
+                    if dynamic_value.type.name == 'void *':
+                        if options.type == 'pointer' and malloc_size == 4096:
+                            error = lldb.SBError()
+                            data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
+                            if data == '\xa1\xa1\xa1\xa1AUTORELEASE!':
+                                description += ', type = (AUTORELEASE!)'
+                    else:
+                        derefed_dynamic_value = dynamic_value.deref
+                        if derefed_dynamic_value:                        
+                            derefed_dynamic_type = derefed_dynamic_value.type
+                            derefed_dynamic_type_size = derefed_dynamic_type.size
+                            derefed_dynamic_type_name = derefed_dynamic_type.name
+                            description += ', type = %s <%u>' % (derefed_dynamic_type_name, derefed_dynamic_type_size)
+                            if offset < derefed_dynamic_type_size:
+                                member_list = list();
+                                get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
+                                if member_list:
+                                    member_path = ''
+                                    for member in member_list:
+                                        member_name = member.name
+                                        if member_name: 
+                                            if member_path:
+                                                member_path += '.'
+                                            member_path += member_name
+                                    if member_path:
+                                        if options.ivar_regex_blacklist:
+                                            for ivar_regex in options.ivar_regex_blacklist:
+                                                if ivar_regex.match(member_path):
+                                                    print_entry = False
+                                        description += ', ivar = %s' % (member_path)
                 if print_entry:
+                    match_idx += 1
                     if description:
                         print description
                         if options.print_type and derefed_dynamic_value:
@@ -248,7 +255,7 @@
                         if options.print_object_description and dynamic_value:
                             desc = dynamic_value.GetObjectDescription()
                             if desc:
-                                print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
+                                print ', po=%s\n' % (desc)
                     if options.memory:
                         cmd_result = lldb.SBCommandReturnObject()
                         memory_command = "memory read -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
@@ -279,6 +286,12 @@
         arg_str_description = 'malloc block containing pointer %s' % arg_str
         if options.format == None: 
             options.format = "A" # 'A' is "address" format
+    elif options.type == 'isa':
+        expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
+        arg_str_description = 'objective C classes with isa %s' % arg_str
+        options.offset = 0
+        if options.format == None: 
+            options.format = "A" # 'A' is "address" format
     elif options.type == 'cstr':
         expr = 'find_cstring_in_heap("%s")' % arg_str
         arg_str_description = 'malloc block containing "%s"' % arg_str
@@ -430,6 +443,37 @@
     else:
         print 'error: no sections were found that match any of %s' % (', '.join(options.section_names))
 
+def objc_refs(debugger, command, result, dict):
+    command_args = shlex.split(command)
+    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
+    description='''Find all heap allocations given one or more objective C class names.'''
+    parser = optparse.OptionParser(description=description, prog='object_refs',usage=usage)
+    add_common_options(parser)
+    try:
+        (options, args) = parser.parse_args(command_args)
+    except:
+        return
+
+    dylid_load_err = load_dylib()
+    if dylid_load_err:
+        print dylid_load_err
+    else:
+        if args:
+            for class_name in args:
+                addr_expr_str = "(void *)[%s class]" % class_name
+                expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
+                if expr_sbvalue.error.Success():
+                    isa = expr_sbvalue.unsigned
+                    if isa:
+                        options.type = 'isa'
+                        heap_search (options, '0x%x' % isa)
+                    else:
+                        print 'error: Can\'t find isa for an ObjC class named "%s"' % (class_name)
+                else:
+                    print 'error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error)
+        else:
+            print 'error: no address expressions were specified'
+
 if __name__ == '__main__':
     lldb.debugger = lldb.SBDebugger.Create()
 
@@ -440,6 +484,7 @@
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info')
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_history malloc_history')
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_refs')
+lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.objc_refs objc_refs')
 print '"ptr_refs", "cstr_refs", "malloc_info", "malloc_history" and "section_ptr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
 
 

Modified: lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp?rev=161724&r1=161723&r2=161724&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp (original)
+++ lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp Fri Aug 10 21:26:26 2012
@@ -399,16 +399,19 @@
     g_matches.clear();
     // Setup "info" to look for a malloc block that contains data
     // that is the a pointer 
-    range_contains_data_callback_info_t data_info;
-    data_info.type = eDataTypeContainsData;      // Check each block for data
-    g_lookup_addr = addr;
-    data_info.data.buffer = (uint8_t *)&addr;    // What data? The pointer value passed in
-    data_info.data.size = sizeof(addr);          // How many bytes? The byte size of a pointer
-    data_info.data.align = sizeof(addr);         // Align to a pointer byte size
-    data_info.match_count = 0;                   // Initialize the match count to zero
-    data_info.done = false;                      // Set done to false so searching doesn't stop
-    range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
-    foreach_zone_in_this_process (&info);
+    if (addr)
+    {
+        range_contains_data_callback_info_t data_info;
+        data_info.type = eDataTypeContainsData;      // Check each block for data
+        g_lookup_addr = addr;
+        data_info.data.buffer = (uint8_t *)&addr;    // What data? The pointer value passed in
+        data_info.data.size = sizeof(addr);          // How many bytes? The byte size of a pointer
+        data_info.data.align = sizeof(addr);         // Align to a pointer byte size
+        data_info.match_count = 0;                   // Initialize the match count to zero
+        data_info.done = false;                      // Set done to false so searching doesn't stop
+        range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
+        foreach_zone_in_this_process (&info);
+    }
     if (g_matches.empty())
         return NULL;
     malloc_match match = { NULL, 0, 0 };





More information about the lldb-commits mailing list