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

Greg Clayton gclayton at apple.com
Wed Jul 11 15:13:18 PDT 2012


Author: gclayton
Date: Wed Jul 11 17:13:18 2012
New Revision: 160083

URL: http://llvm.org/viewvc/llvm-project?rev=160083&view=rev
Log:
Added the ability to search through sections for pointer data.


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=160083&r1=160082&r2=160083&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap.py (original)
+++ lldb/trunk/examples/darwin/heap_find/heap.py Wed Jul 11 17:13:18 2012
@@ -13,6 +13,7 @@
 import optparse
 import os
 import os.path
+import re
 import shlex
 import string
 import tempfile
@@ -112,14 +113,24 @@
                 member_list.append(member)
                 get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
                 return
+
+def append_regex_callback(option, opt, value, parser):
+    try:
+        ivar_regex = re.compile(value)
+        parser.values.ivar_regex_blacklist.append(ivar_regex)
+    except:
+        print 'error: an exception was thrown when compiling the ivar regular expression for "%s"' % value
     
 def add_common_options(parser):
     parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
+    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)
     parser.add_option('-o', '--po', action='store_true', dest='print_object_description', help='print the object descriptions for any matches', default=False)
     parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False)
     parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None)
+    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')
     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)
 
 def dump_stack_history_entry(stack_history_entry, idx):
     address = int(stack_history_entry.address)
@@ -172,43 +183,21 @@
                 dump_stack_history_entry(stack_history_entry, idx)
                 idx = idx + 1
                 stack_history_entry = expr_value[idx]
-        else:
-            print 'error: expression returned => %s' % (expr_sbvalue)
     else:
         print 'error: expression failed "%s" => %s' % (expr, expr_sbvalue.error)
     
-    
-def heap_search(options, arg_str):
-    dylid_load_err = load_dylib()
-    if dylid_load_err:
-        print dylid_load_err
-        return
-    expr = None
-    arg_str_description = arg_str
-    default_memory_format = "Y" # 'Y' is "bytes with ASCII" format
-    #memory_chunk_size = 1
-    if options.type == 'pointer':
-        expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
-        arg_str_description = 'malloc block containing pointer %s' % arg_str
-        default_memory_format = "A" # 'A' is "address" format
-        #memory_chunk_size = lldb.process.GetAddressByteSize()
-    elif options.type == 'cstr':
-        expr = 'find_cstring_in_heap("%s")' % arg_str
-        arg_str_description = 'malloc block containing "%s"' % arg_str
-    elif options.type == 'addr':
-        expr = 'find_block_for_address((void *)%s)' % arg_str
-        arg_str_description = 'malloc block for %s' % arg_str
-    else:
-        print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
-        return
-    
-    expr_sbvalue = lldb.frame.EvaluateExpression (expr)
+
+def display_match_results (options, arg_str_description, expr_sbvalue, print_no_matches = True):
     if expr_sbvalue.error.Success():
         if expr_sbvalue.unsigned:
             match_value = lldb.value(expr_sbvalue)  
             i = 0
             while 1:
+                print_entry = True
                 match_entry = match_value[i]; i += 1
+                if i >= options.max_matches:
+                    print 'error: the max number of matches (%u) was reached, use the --max-matches option to get more results' % (options.max_matches)
+                    break
                 malloc_addr = match_entry.addr.sbvalue.unsigned
                 if malloc_addr == 0:
                     break
@@ -220,13 +209,13 @@
                 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!)'
-                    print description
                 else:
                     derefed_dynamic_value = dynamic_value.deref
                     if derefed_dynamic_value:                        
@@ -246,32 +235,61 @@
                                             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)
-                            print description
-                            if derefed_dynamic_value:
-                                print derefed_dynamic_value
-                            if options.print_object_description:
-                                desc = dynamic_value.GetObjectDescription()
-                                if desc:
-                                    print '  (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
-                if options.memory:
-                    memory_format = options.format
-                    if not memory_format:
-                        memory_format = default_memory_format
-                    cmd_result = lldb.SBCommandReturnObject()
-                    #count = malloc_size / memory_chunk_size
-                    memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size)
-                    lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
-                    print cmd_result.GetOutput()
-                if options.stack_history:
-                    dump_stack_history_entries(malloc_addr, 1)
-                elif options.stack:
-                    dump_stack_history_entries(malloc_addr, 0)
-        else:
-            print '%s %s was not found in any malloc blocks' % (options.type, arg_str)
+                if print_entry:
+                    if description:
+                        print description
+                        if options.print_type and derefed_dynamic_value:
+                            print derefed_dynamic_value
+                        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)
+                    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)
+                        lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
+                        print cmd_result.GetOutput()
+                    if options.stack_history:
+                        dump_stack_history_entries(malloc_addr, 1)
+                    elif options.stack:
+                        dump_stack_history_entries(malloc_addr, 0)
+            return i
+        elif print_no_matches:
+            print 'no matches found for %s' % (arg_str_description)
     else:
         print expr_sbvalue.error
-    print     
+    return 0
+    
+def heap_search(options, arg_str):
+    dylid_load_err = load_dylib()
+    if dylid_load_err:
+        print dylid_load_err
+        return
+    expr = None
+    arg_str_description = arg_str
+    if options.format == None: 
+        options.format = "Y" # 'Y' is "bytes with ASCII" format
+    if options.type == 'pointer':
+        expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
+        arg_str_description = 'malloc block containing pointer %s' % arg_str
+        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
+    elif options.type == 'addr':
+        expr = 'find_block_for_address((void *)%s)' % arg_str
+        arg_str_description = 'malloc block for %s' % arg_str
+    else:
+        print 'error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type
+        return
+    
+    display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr))
     
 def ptr_refs(debugger, command, result, dict):
     command_args = shlex.split(command)
@@ -366,6 +384,52 @@
         else:
             print 'error: no address expressions were specified'
 
+def section_ptr_refs(debugger, command, result, dict):
+    command_args = shlex.split(command)
+    usage = "usage: %prog [options] <EXPR> [EXPR ...]"
+    description='''Searches section contents for pointer values in darwin user space programs.'''
+    parser = optparse.OptionParser(description=description, prog='section_ptr_refs',usage=usage)
+    add_common_options(parser)
+    parser.add_option('--section', action='append', type='string', dest='section_names', help='section name to search', default=list())
+    try:
+        (options, args) = parser.parse_args(command_args)
+    except:
+        return
+
+    options.type = 'pointer'
+    
+    sections = list()
+    section_modules = list()
+    if not options.section_names:
+        print 'error: at least one section must be specified with the --section option'
+        return
+
+    for module in lldb.target.modules:
+        for section_name in options.section_names:
+            section = module.section[section_name]
+            if section:
+                sections.append (section)
+                section_modules.append (module)
+    if sections:
+        dylid_load_err = load_dylib()
+        if dylid_load_err:
+            print dylid_load_err
+            return
+        for expr_str in args:
+            for (idx, section) in enumerate(sections):
+                expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (section.addr.load_addr, section.size, expr_str)
+                arg_str_description = 'section %s.%s containing "%s"' % (section_modules[idx].file.fullpath, section.name, expr_str)
+                num_matches = display_match_results (options, arg_str_description, lldb.frame.EvaluateExpression (expr), False)
+                if num_matches:
+                    if num_matches < options.max_matches:
+                        options.max_matches = options.max_matches - num_matches
+                    else:
+                        options.max_matches = 0
+                if options.max_matches == 0:
+                    return
+    else:
+        print 'error: no sections were found that match any of %s' % (', '.join(options.section_names))
+
 if __name__ == '__main__':
     lldb.debugger = lldb.SBDebugger.Create()
 
@@ -375,7 +439,8 @@
 lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs')
 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')
-print '"ptr_refs", "cstr_refs", "malloc_info", and "malloc_history" commands have been installed, use the "--help" options on these commands for detailed help.'
+lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_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=160083&r1=160082&r2=160083&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp (original)
+++ lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp Wed Jul 11 17:13:18 2012
@@ -416,6 +416,33 @@
     return g_matches.data();
 }
 
+//----------------------------------------------------------------------
+// find_pointer_in_memory
+//
+// Finds a pointer value inside one or more currently valid malloc
+// blocks.
+//----------------------------------------------------------------------
+malloc_match *
+find_pointer_in_memory (uint64_t memory_addr, uint64_t memory_size, const void * addr)
+{
+    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_info_callback (mach_task_self(), &data_info, stack_logging_type_generic, memory_addr, memory_size);
+    if (g_matches.empty())
+        return NULL;
+    malloc_match match = { NULL, 0, 0 };
+    g_matches.push_back(match);
+    return g_matches.data();
+}
 
 //----------------------------------------------------------------------
 // find_cstring_in_heap





More information about the lldb-commits mailing list