#!/usr/bin/python

#----------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
#
# # To use this in the embedded python interpreter using "lldb" just
# import it with the full path using the "command script import" 
# command
#   (lldb) command script import /path/to/cmdtemplate.py
#----------------------------------------------------------------------

import commands
import platform
import os
import re
import signal
import sys

try: 
    # Just try for LLDB in case PYTHONPATH is already correctly setup
    import lldb
except ImportError:
    lldb_python_dirs = list()
    # lldb is not in the PYTHONPATH, try some defaults for the current platform
    platform_system = platform.system()
    if platform_system == 'Darwin':
        # On Darwin, try the currently selected Xcode directory
        xcode_dir = commands.getoutput("xcode-select --print-path")
        if xcode_dir:
            lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
            lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
        lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
    success = False
    for lldb_python_dir in lldb_python_dirs:
        if os.path.exists(lldb_python_dir):
            if not (sys.path.__contains__(lldb_python_dir)):
                sys.path.append(lldb_python_dir)
                try: 
                    import lldb
                except ImportError:
                    pass
                else:
                    print 'imported lldb from: "%s"' % (lldb_python_dir)
                    success = True
                    break
    if not success:
        print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
        sys.exit(1)

import commands
import optparse
import shlex
import time

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)
    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 the platform to use when creating the debug target. Valid values include "localhost", "darwin-kernel", "ios-simulator", "remote-freebsd", "remote-macosx", "remote-ios", "remote-linux".')
    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('-d', '--debug', action='store_true', dest='debug', help='Pause 10 seconds to wait for a debugger to attach.', 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, options, type):
    print type
    typename = type.GetName()
    # print 'type: %s' % (typename)
    (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
    #     print '%+4u <%u> padding' % (end_offset, last_member_padding)
    #     padding += last_member_padding
    print 'Total byte size: %u' % (byte_size)
    print 'Total pad bytes: %u' % (padding)
    if padding > 0:
        print 'Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)
    print

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, byte_size, '    ' * depth, typename, member_name)
    else:
        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):
            member_type = member.GetType()
            member_canonical_type = member_type.GetCanonicalType()
            member_type_class = member_canonical_type.GetTypeClass()
            member_name = member.GetName()
            member_offset = member.GetOffsetInBytes()
            member_total_offset = member_offset + base_offset
            member_byte_size = member_type.GetByteSize()
            member_is_class_or_struct = False
            if member_type_class == lldb.eTypeClassStruct or member_type_class == lldb.eTypeClassClass:
                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))
                prev_end_offset = ptr_size
            else:
                if prev_end_offset < member_total_offset:
                    member_padding = member_total_offset - prev_end_offset
                    padding = padding + member_padding
                    print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, '    ' * (depth + 1))
        
            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_typename, member.GetBitfieldSizeInBits(), member_name)
                else:
                    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
            print '%+4u <%3u> %s<PADDING>' % (prev_end_offset, last_member_padding, '    ' * (depth + 1))
            padding += last_member_padding
    else:
        if type.IsPolymorphicClass():
            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 + byte_size
    
    return (prev_end_offset, padding)
    
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)
    parser = create_types_options(True)
    try:
        (options, args) = parser.parse_args(command_args)
    except:
        # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
        # (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 to process %d" % os.getpid()
        os.kill(os.getpid(), signal.SIGSTOP)
        
    for path in args:
    # in a command - the lldb.* convenience variables are not to be used
    # and their values (if any) are undefined
    # this is the best practice to access those objects from within a command
        error = lldb.SBError()
        target = debugger.CreateTarget (path,
                                        options.arch,
                                        options.platform,
                                        True,
                                        error)
        if error.Fail():
            print error.GetCString()
            continue
        verify_types (target, options)
    
elif getattr(lldb, 'debugger', None):
    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'