[Lldb-commits] [lldb] r184628 - Added a regex that can be specified to avoid showing contents on types that match. Also split things up a bit so this can be run as a stand alone script or in lldb.

Greg Clayton gclayton at apple.com
Fri Jun 21 18:42:49 PDT 2013


Author: gclayton
Date: Fri Jun 21 20:42:49 2013
New Revision: 184628

URL: http://llvm.org/viewvc/llvm-project?rev=184628&view=rev
Log:
Added a regex that can be specified to avoid showing contents on types that match. Also split things up a bit so this can be run as a stand alone script or in lldb.


Modified:
    lldb/trunk/examples/python/types.py

Modified: lldb/trunk/examples/python/types.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/types.py?rev=184628&r1=184627&r2=184628&view=diff
==============================================================================
--- lldb/trunk/examples/python/types.py (original)
+++ lldb/trunk/examples/python/types.py Fri Jun 21 20:42:49 2013
@@ -12,6 +12,7 @@
 import commands
 import platform
 import os
+import re
 import sys
 
 try: 
@@ -50,26 +51,48 @@ import optparse
 import shlex
 import time
 
-def create_types_options():
-    usage = "usage: %prog [options]"
-    description='''This command will help you verify that types in your program
-are packed efficiently by showing all types and their sizes and showing the 
-padding bytes that waste space.
+def regex_option_callback(option, opt_str, value, parser):
+    if opt_str == "--std":
+        value = '^std::'
+    regex = re.compile(value)
+    parser.values.skip_type_regexes.append (regex)
+
+def create_types_options(for_lldb_command):
+    if for_lldb_command:
+        usage = "usage: %prog [options]"
+        description='''This command will help check for padding in between
+base classes and members in structs and classes. It will summarize the types
+and how much padding was found. If no types are specified with the --types TYPENAME
+option, all structure and class types will be verified. If no modules are 
+specified with the --module option, only the target's main executable will be
+searched.
+'''
+    else:
+        usage = "usage: %prog [options] EXEPATH [EXEPATH ...]"
+        description='''This command will help check for padding in between
+base classes and members in structures and classes. It will summarize the types
+and how much padding was found. One or more paths to executable files must be
+specified and targets will be created with these modules. If no types are 
+specified with the --types TYPENAME option, all structure and class types will
+be verified in all specified modules.
 '''
     parser = optparse.OptionParser(description=description, prog='framestats',usage=usage)
-    parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
-    parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name')
+    if not for_lldb_command:
+        parser.add_option('-a', '--arch', type='string', dest='arch', help='The architecture to use when creating the debug target.', default=None)
+        parser.add_option('-p', '--platform', type='string', metavar='platform', dest='platform', help='specify one platform by name')
     parser.add_option('-m', '--module', action='append', type='string', metavar='MODULE', dest='modules', help='Specify one or more modules which will be used to verify the types.', default=[])
-    parser.add_option('-t', '--type', action='append', type='string', metavar='TYPENAME', dest='typenames', help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', default=[])
     parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', default=False)
-    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False)
+    parser.add_option('-t', '--type', action='append', type='string', metavar='TYPENAME', dest='typenames', help='Specify one or more type names which should be verified. If no type names are specified, all class and struct types will be verified.', default=[])
+    parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='Enable verbose logging and information.', default=False)
+    parser.add_option('-s', '--skip-type-regex', action="callback", callback=regex_option_callback, type='string', metavar='REGEX', dest='skip_type_regexes', help='Regular expressions that, if they match the current member typename, will cause the type to no be recursively displayed.', default=[])
+    parser.add_option('--std', action="callback", callback=regex_option_callback, metavar='REGEX', dest='skip_type_regexes', help="Don't' recurse into types in the std namespace.", default=[])
     return parser
 
-def verify_type (target, type):
+def verify_type (target, options, type):
     print type
     typename = type.GetName()
     # print 'type: %s' % (typename)
-    (end_offset, padding) = verify_type_recursive (target, type, None, 0, 0, 0)
+    (end_offset, padding) = verify_type_recursive (target, options, type, None, 0, 0, 0)
     byte_size = type.GetByteSize()
     # if end_offset < byte_size:
     #     last_member_padding = byte_size - end_offset
@@ -81,15 +104,20 @@ def verify_type (target, type):
         print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)
     print
 
-def verify_type_recursive (target, type, member_name, depth, base_offset, padding):
+def verify_type_recursive (target, options, type, member_name, depth, base_offset, padding):
     prev_end_offset = base_offset
     typename = type.GetName()
     byte_size = type.GetByteSize()
     if member_name and member_name != typename:
-        print '%+4u <%3u> %s%s %s;' % (base_offset, type.GetByteSize(), '    ' * depth, typename, member_name)
+        print '%+4u <%3u> %s%s %s;' % (base_offset, byte_size, '    ' * depth, typename, member_name)
     else:
-        print '%+4u <%3u> %s%s' % (base_offset, type.GetByteSize(), '    ' * depth, typename)
+        print '%+4u {%3u} %s%s' % (base_offset, byte_size, '    ' * depth, typename)
     
+    for type_regex in options.skip_type_regexes:
+        match = type_regex.match (typename)
+        if match:
+            return (base_offset + byte_size, padding)
+                
     members = type.members
     if members:
         for member_idx, member in enumerate(members):
@@ -100,9 +128,9 @@ def verify_type_recursive (target, type,
             member_offset = member.GetOffsetInBytes()
             member_total_offset = member_offset + base_offset
             member_byte_size = member_type.GetByteSize()
-            is_class_or_struct = False
+            member_is_class_or_struct = False
             if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass:
-                is_class_or_struct = True
+                member_is_class_or_struct = True
             if member_idx == 0 and member_offset == target.GetAddressByteSize() and type.IsPolymorphicClass():
                 ptr_size = target.GetAddressByteSize()
                 print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, '    ' * (depth + 1))
@@ -113,14 +141,15 @@ def verify_type_recursive (target, type,
                     padding = padding + member_padding
                     print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, '    ' * (depth + 1))
         
-            if is_class_or_struct:
-                (prev_end_offset, padding) = verify_type_recursive (target, member_canonical_type, member_name, depth + 1, member_total_offset, padding)
+            if member_is_class_or_struct:
+                (prev_end_offset, padding) = verify_type_recursive (target, options, member_canonical_type, member_name, depth + 1, member_total_offset, padding)
             else:
                 prev_end_offset = member_total_offset + member_byte_size
+                member_typename = member_type.GetName()
                 if member.IsBitfield():
-                    print '%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, '    ' * (depth + 1), member_type.GetName(), member.GetBitfieldSizeInBits(), member_name)
+                    print '%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, '    ' * (depth + 1), member_typename, member.GetBitfieldSizeInBits(), member_name)
                 else:
-                    print '%+4u <%3u> %s%s %s;' % (member_total_offset, member_byte_size, '    ' * (depth + 1), member_type.GetName(), member_name)
+                    print '%+4u <%3u> %s%s %s;' % (member_total_offset, member_byte_size, '    ' * (depth + 1), member_typename, member_name)
     
         if prev_end_offset < byte_size:
             last_member_padding = byte_size - prev_end_offset
@@ -131,19 +160,15 @@ def verify_type_recursive (target, type,
             ptr_size = target.GetAddressByteSize()
             print '%+4u <%3u> %s__vtbl_ptr_type * _vptr;' % (prev_end_offset, ptr_size, '    ' * (depth + 1))
             prev_end_offset = ptr_size
-        prev_end_offset = base_offset + type.GetByteSize()
+        prev_end_offset = base_offset + byte_size
     
     return (prev_end_offset, padding)
     
-def types_command (debugger, command, result, dict):
+def check_padding_command (debugger, command, result, dict):
     # Use the Shell Lexer to properly parse up command options just like a 
     # shell would
     command_args = shlex.split(command)
-    verify_types(debugger, command_args)
-    
-def verify_types (debugger, command_args):
-
-    parser = create_types_options()
+    parser = create_types_options(True)
     try:
         (options, args) = parser.parse_args(command_args)
     except:
@@ -151,13 +176,57 @@ def verify_types (debugger, command_args
         # (courtesy of OptParse dealing with argument errors by throwing SystemExit)
         result.SetStatus (lldb.eReturnStatusFailed)
         return "option parsing failed" # returning a string is the same as returning an error whose description is the string
+    verify_types(options, debugger.GetSelectedTarget(), command_args)
+    
+    
+def verify_types (target, options):
+
+    if not target:
+        print 'error: invalid target'
+        return
+    
+    modules = list()
+    if len(options.modules) == 0:
+        # Append just the main executable if nothing was specified
+        module = target.modules[0]
+        if module:
+            modules.append(module)
+    else:
+        for module_name in options.modules:
+            module = lldb.target.module[module_name]
+            if module:
+                modules.append(module)
+    
+    if modules:
+        for module in modules:
+            print 'module: %s' % (module.file)
+            if options.typenames:
+                for typename in options.typenames:
+                    types = module.FindTypes(typename)
+                    if types.GetSize():
+                        print 'Found %u types matching "%s" in "%s"' % (len(types), typename, module.file)
+                        for type in types:
+                            verify_type (target, options, type)
+                    else:
+                        print 'error: no type matches "%s" in "%s"' % (typename, module.file)
+            else:
+                types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
+                print 'Found %u types in "%s"' % (len(types), module.file)
+                for type in types:
+                    verify_type (target, options, type)
+    else:
+        print 'error: no modules'
+
+if __name__ == '__main__':
+    debugger = lldb.SBDebugger.Create()
+    parser = create_types_options(False)
+    
+    # try:
+    (options, args) = parser.parse_args(sys.argv[1:])
+    # except:
+    #     print "error: option parsing failed" 
+    #     sys.exit(1)
     
-    if options.debug:
-        print 'Waiting for debugger to attach...'
-        for i in range(10):
-            time.sleep(1)
-            print '.'
-        
     for path in args:
     # in a command - the lldb.* convenience variables are not to be used
     # and their values (if any) are undefined
@@ -171,42 +240,8 @@ def verify_types (debugger, command_args
         if error.Fail():
             print error.GetCString()
             continue
+        verify_types (target, options)
     
-        modules = list()
-        if len(options.modules) == 0:
-            # Append just the main executable if nothing was specified
-            module = target.modules[0]
-            if module:
-                modules.append(module)
-        else:
-            for module_name in options.modules:
-                module = lldb.target.module[module_name]
-                if module:
-                    modules.append(module)
-        
-        if modules:
-            for module in modules:
-                print 'module: %s' % (module.file)
-                if options.typenames:
-                    for typename in options.typenames:
-                        types = module.FindTypes(typename)
-                        if types.GetSize():
-                            print 'Found %u types matching "%s" in "%s"' % (len(types), typename, module.file)
-                            for type in types:
-                                verify_type (target, type)
-                        else:
-                            print 'error: no type matches "%s" in "%s"' % (typename, module.file)
-                else:
-                    types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
-                    print 'Found %u types in "%s"' % (len(types), module.file)
-                    for type in types:
-                        verify_type (target, type)
-        else:
-            print 'error: no modules'
-
-if __name__ == '__main__':
-    debugger = lldb.SBDebugger.Create()
-    verify_types (debugger, sys.argv[1:])
 elif getattr(lldb, 'debugger', None):
-    lldb.debugger.HandleCommand('command script add -f types.types_command types')
-    print '"types" command installed, use the "--help" option for detailed help'
\ No newline at end of file
+    lldb.debugger.HandleCommand('command script add -f types.check_padding_command check_padding')
+    print '"check_padding" command installed, use the "--help" option for detailed help'
\ No newline at end of file





More information about the lldb-commits mailing list