#!/usr/bin/env python

# Copyright (C) 2011-2015 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

import sys
import getopt
import argparse
import os
import subprocess;


framework = "WebCore"
build_directory = ""
config = "Release"

def webkit_build_dir():
    scriptpath = os.path.dirname(os.path.realpath(__file__))
    return subprocess.check_output([os.path.join(scriptpath, "webkit-build-directory"), "--top-level"]).strip()

def developer_dir():
    return subprocess.check_output(["xcode-select", "--print-path"])

def import_lldb():
    xcode_contents_path = os.path.split(developer_dir())[0]
    lldb_framework_path = os.path.join(xcode_contents_path, "SharedFrameworks", "LLDB.framework", "Resources", "Python")
    sys.path.append(lldb_framework_path)

    LLDB_MODULE_NAME = "lldb"
    try:
        globals()[LLDB_MODULE_NAME] = __import__(LLDB_MODULE_NAME)
    except ImportError:
        print "Failed to import {} from {}".format(LLDB_MODULE_NAME, lldb_framework_path)
        sys.exit(1)

def find_build_directory():
    return


def verify_type(target, type):
    typename = type.GetName()
    (end_offset, padding) = verify_type_recursive(target, type, None, 0, 0, 0)
    byte_size = type.GetByteSize()
    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, 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)

    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, 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 dump_class(framework, classname):
    debugger = lldb.SBDebugger.Create()
    debugger.SetAsync (False)
    target = debugger.CreateTargetWithFileAndArch(framework, lldb.LLDB_ARCH_DEFAULT)
    if not target:
        print "Failed to make target for " + framework;
        sys.exit(1)

    module = target.GetModuleAtIndex(0)
    if not module:
        print "Failed to get first module in " + framework;
        sys.exit(1)

    types = module.FindTypes(classname)
    if types.GetSize():
        print 'Found %u types matching "%s" in "%s"' % (len(types), classname, module.file)
        for type in types:
            verify_type(target, type)
    else:
        print 'error: no type matches "%s" in "%s"' % (classname, module.file)

    lldb.SBDebugger.Destroy(debugger)

def main():
    parser = argparse.ArgumentParser(description='Dumps the in-memory layout of the given class or classes, showing padding holes.')
    parser.add_argument('framework', metavar='framework',
        help='name of the framework containing the class (e.g. "WebCore")')
    parser.add_argument('classname', metavar='classname',
        help='name of the class or struct to dump')

    parser.add_argument('-b', '--build-directory', dest='build_directory', action='store',
        help='Path to the directory under which build files are kept (should not include configuration)')

    parser.add_argument('-c', '--configuration', dest='config', action='store',
        help='Configuration (Debug or Release)')

    args = parser.parse_args()
    build_dir = webkit_build_dir()

    if args.config == None:
        args.config = "Release"

    if not args.build_directory == None:
        build_dir = args.build_directory

    target_path = os.path.join(build_dir, args.config, args.framework + ".framework", args.framework);
    import_lldb()
    dump_class(target_path, args.classname)

if __name__ == "__main__":
    main()
