#!/usr/bin/env 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
#----------------------------------------------------------------------

from __future__ import print_function

import platform
import os
import re
import signal
import sys
import subprocess

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 = subprocess.check_output("xcode-select --print-path", shell=True)
        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 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)
        # returning a string is the same as returning an error whose
        # description is the string
        return "option parsing failed"
    verify_types(debugger.GetSelectedTarget(), options)


@lldb.command("parse_all_struct_class_types")
def parse_all_struct_class_types(debugger, command, result, dict):
    command_args = shlex.split(command)
    for f in command_args:
        error = lldb.SBError()
        target = debugger.CreateTarget(f, None, None, False, error)
        module = target.GetModuleAtIndex(0)
        print("Parsing all types in '%s'" % (module))
        types = module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
        for t in types:
            print(t)
        print("")


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')
