WebKit Bugzilla
Attachment 343809 Details for
Bug 187141
: Add the first unit test for dump_class_layout
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-187141-20180628085113.patch (text/plain), 27.29 KB, created by
Simon Fraser (smfr)
on 2018-06-28 08:51:14 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Simon Fraser (smfr)
Created:
2018-06-28 08:51:14 PDT
Size:
27.29 KB
patch
obsolete
>Subversion Revision: 233306 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 5ea571a7e79dfa273a49ce110cc43a39f853055b..8abcc721153ffeb6bbdc09a0fea60bc82db1ce04 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,46 @@ >+2018-06-28 Simon Fraser <simon.fraser@apple.com> >+ >+ Add the first unit test for dump_class_layout >+ https://bugs.webkit.org/show_bug.cgi?id=187141 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Move the guts of dump_class_layout to Python module Tools/lldb/lldb_dump_class_layout.py >+ so that it can be pulled in by the unit test file. >+ >+ Add Tools/lldb/dump_class_layout_unittest.py which does a single unit test for the layout >+ of a basic class. >+ >+ Add lldbWebKitTester/DumpClassLayoutTesting.cpp which will house future class layout unit >+ tests. >+ >+ * Scripts/dump-class-layout: >+ (webkit_build_dir): >+ (main): >+ (verify_type): Deleted. >+ (verify_type_recursive): Deleted. >+ (get_first_file_architecture): Deleted. >+ (dump_class): Deleted. >+ * lldb/dump_class_layout_unittest.py: Added. >+ (TestDumpClassLayout): >+ (TestDumpClassLayout.setUp): >+ (TestDumpClassLayout.test_BasicClassLayout): >+ * lldb/lldbWebKitTester/DumpClassLayoutTesting.cpp: Copied from Tools/lldb/lldbWebKitTester/main.cpp. >+ (avoidClassDeadStripping): >+ * lldb/lldbWebKitTester/DumpClassLayoutTesting.h: Copied from Tools/lldb/lldbWebKitTester/main.cpp. >+ * lldb/lldbWebKitTester/lldbWebKitTester.xcodeproj/project.pbxproj: >+ * lldb/lldbWebKitTester/main.cpp: >+ (main): >+ * lldb/lldb_dump_class_layout.py: Added. >+ (ClassLayoutDumper): >+ (ClassLayoutDumper.__init__): >+ (ClassLayoutDumper._get_first_file_architecture): >+ (ClassLayoutDumper.verify_type): >+ (ClassLayoutDumper.verify_type_recursive): >+ (ClassLayoutDumper._class_layout_as_string): >+ (ClassLayoutDumper.dump_to_string): >+ (ClassLayoutDumper.dump): >+ > 2018-06-28 Simon Fraser <simon.fraser@apple.com> > > The lldb vector summary provider always shows zero capacity >diff --git a/Tools/Scripts/dump-class-layout b/Tools/Scripts/dump-class-layout >index 6f6eba42de8175362b2c21977916d874b5504cd5..e5d9d8d86e314ba846380ac6a4cc6e6dd2d24979 100755 >--- a/Tools/Scripts/dump-class-layout >+++ b/Tools/Scripts/dump-class-layout >@@ -31,9 +31,11 @@ import os > import subprocess > from sets import Set > >-from webkitpy.common.system.systemhost import SystemHost >-sys.path.append(SystemHost().path_to_lldb_python_directory()) >-import lldb >+up = os.path.dirname >+tools_directory = up(up(os.path.abspath(__file__))) >+sys.path.insert(0, os.path.join(tools_directory, "lldb")) >+ >+from lldb_dump_class_layout import ClassLayoutDumper > > framework = "WebCore" > build_directory = "" >@@ -44,120 +46,6 @@ 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 verify_type(target, type): >- typename = type.GetName() >- seenOffset = Set() >- (end_offset, padding) = verify_type_recursive(target, type, None, 0, 0, 0, seenOffset) >- 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, seenOffset): >- 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_offset, member_name) in seenOffset: >- continue >- seenOffset.add((member_offset, member_name)) >- >- 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, seenOffset) >- 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 get_first_file_architecture(framework_path): >- p = re.compile('shared library +(\w+)$') >- file_result = subprocess.check_output(["file", framework_path]).split('\n') >- arches = [] >- for line in file_result: >- match = p.search(line) >- if match: >- arches.append(match.group(1)); >- >- if len(arches) > 1: >- print 'Found architectures %s, using %s' % (arches, arches[0]) >- >- if len(arches) > 0: >- return arches[0] >- >- return lldb.LLDB_ARCH_DEFAULT >- >-def dump_class(framework_path, classname, architecture): >- debugger = lldb.SBDebugger.Create() >- debugger.SetAsync(False) >- if not architecture: >- architecture = get_first_file_architecture(framework_path) >- >- target = debugger.CreateTargetWithFileAndArch(framework_path, architecture) >- if not target: >- print "Failed to make target for " + framework_path; >- sys.exit(1) >- >- module = target.GetModuleAtIndex(0) >- if not module: >- print "Failed to get first module in " + framework_path; >- sys.exit(1) >- >- types = module.FindTypes(classname) >- if types.GetSize(): >- print 'Found %u types matching "%s" in "%s" for %s' % (len(types), classname, module.file, architecture) >- 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', >@@ -184,7 +72,7 @@ def main(): > build_dir = args.build_directory > > target_path = os.path.join(build_dir, args.config, args.framework + ".framework", args.framework); >- dump_class(target_path, args.classname, args.arch) >+ ClassLayoutDumper(target_path, args.classname, args.arch).dump() > > if __name__ == "__main__": > main() >diff --git a/Tools/lldb/dump_class_layout_unittest.py b/Tools/lldb/dump_class_layout_unittest.py >new file mode 100755 >index 0000000000000000000000000000000000000000..9346947f9dd07ccf15cb815e6cee2177dd1c7a54 >--- /dev/null >+++ b/Tools/lldb/dump_class_layout_unittest.py >@@ -0,0 +1,62 @@ >+#!/usr/bin/env python >+# -*- coding: utf-8 -*- >+# >+# Copyright (C) 2018 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 atexit >+import lldb >+import os >+import sys >+import unittest >+ >+from webkitpy.common.system.systemhost import SystemHost >+from webkitpy.port.config import Config >+ >+from lldb_dump_class_layout import ClassLayoutDumper >+ >+# Run these tests with ./Tools/Scripts/test-webkitpy dump_class_layout_unittest >+ >+class TestDumpClassLayout(unittest.TestCase): >+ >+ def setUp(self): >+ super(TestDumpClassLayout, self).setUp() >+ self.addTypeEqualityFunc(str, self.assertMultiLineEqual) >+ >+ def test_BasicClassLayout(self): >+ LLDB_WEBKIT_TESTER_NAME = 'lldbWebKitTester' >+ >+ host = SystemHost() >+ config = Config(host.executive, host.filesystem) >+ lldbWebKitTesterExecutable = os.path.join(config.build_directory(config.default_configuration()), LLDB_WEBKIT_TESTER_NAME) >+ >+ basic_class_dump = ClassLayoutDumper(lldbWebKitTesterExecutable, 'BasicClassLayout', 'x86_64').dump_to_string() >+ >+ BASIC_CLASS_LAYOUT_RESULT = """ +0 { 8} BasicClassLayout >+ +0 < 4> int intMember; >+ +4 < 1> bool boolMember; >+ +5 < 3> <PADDING> >+Total byte size: 8 >+Total pad bytes: 3 >+Padding percentage: 37.50 % >+""" >+ self.assertEqual(basic_class_dump, BASIC_CLASS_LAYOUT_RESULT) >diff --git a/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.cpp b/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..9f7498408da1fa8be5f55ab65cef01bf593ce98b >--- /dev/null >+++ b/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.cpp >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#include "DumpClassLayoutTesting.h" >+ >+class BasicClassLayout { >+ int intMember; >+ bool boolMember; >+}; >+ >+void avoidClassDeadStripping() >+{ >+ BasicClassLayout basicClassInstance; >+} >diff --git a/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.h b/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.h >new file mode 100644 >index 0000000000000000000000000000000000000000..aeaa7b9b7c4812d90cc44c939824978c4f121f98 >--- /dev/null >+++ b/Tools/lldb/lldbWebKitTester/DumpClassLayoutTesting.h >@@ -0,0 +1,28 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+void avoidClassDeadStripping(); >diff --git a/Tools/lldb/lldbWebKitTester/lldbWebKitTester.xcodeproj/project.pbxproj b/Tools/lldb/lldbWebKitTester/lldbWebKitTester.xcodeproj/project.pbxproj >index c52a15e128337b0b6e4839509054ac3da7316217..283299a5999268421750f5dcf230ed47842a90a2 100644 >--- a/Tools/lldb/lldbWebKitTester/lldbWebKitTester.xcodeproj/project.pbxproj >+++ b/Tools/lldb/lldbWebKitTester/lldbWebKitTester.xcodeproj/project.pbxproj >@@ -7,6 +7,7 @@ > objects = { > > /* Begin PBXBuildFile section */ >+ 0FC1C35420E5391E001E9FB0 /* DumpClassLayoutTesting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC1C35320E5391E001E9FB0 /* DumpClassLayoutTesting.cpp */; }; > 7CB6844B1AFA7978002B305C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CB6844A1AFA7978002B305C /* main.cpp */; }; > CE6C3AFF20C0B17B003E33D8 /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE6C3AFE20C0B17B003E33D8 /* libWTF.a */; }; > CE6C3B0120C0C444003E33D8 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CE6C3B0020C0C443003E33D8 /* libicucore.dylib */; }; >@@ -25,6 +26,8 @@ > /* End PBXCopyFilesBuildPhase section */ > > /* Begin PBXFileReference section */ >+ 0FC1C35320E5391E001E9FB0 /* DumpClassLayoutTesting.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DumpClassLayoutTesting.cpp; sourceTree = "<group>"; }; >+ 0FC1C35520E53932001E9FB0 /* DumpClassLayoutTesting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DumpClassLayoutTesting.h; sourceTree = "<group>"; }; > 7C2227511AFC4D9C008C3338 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; }; > 7C2227521AFC4D9C008C3338 /* lldbWebKitTester.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lldbWebKitTester.xcconfig; sourceTree = "<group>"; }; > 7C2227531AFC4D9C008C3338 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; }; >@@ -78,6 +81,8 @@ > CE3F4424205C66D9007195B3 /* lldbWebKitTester */ = { > isa = PBXGroup; > children = ( >+ 0FC1C35320E5391E001E9FB0 /* DumpClassLayoutTesting.cpp */, >+ 0FC1C35520E53932001E9FB0 /* DumpClassLayoutTesting.h */, > 7CB6844A1AFA7978002B305C /* main.cpp */, > ); > name = lldbWebKitTester; >@@ -142,6 +147,7 @@ > isa = PBXSourcesBuildPhase; > buildActionMask = 2147483647; > files = ( >+ 0FC1C35420E5391E001E9FB0 /* DumpClassLayoutTesting.cpp in Sources */, > 7CB6844B1AFA7978002B305C /* main.cpp in Sources */, > ); > runOnlyForDeploymentPostprocessing = 0; >diff --git a/Tools/lldb/lldbWebKitTester/main.cpp b/Tools/lldb/lldbWebKitTester/main.cpp >index 4e11ab79122619e0aa683b81fa20ab7293148b45..9c72441addbcdb917b331e006f400317bfef1b31 100644 >--- a/Tools/lldb/lldbWebKitTester/main.cpp >+++ b/Tools/lldb/lldbWebKitTester/main.cpp >@@ -23,6 +23,7 @@ > * THE POSSIBILITY OF SUCH DAMAGE. > */ > >+#include "DumpClassLayoutTesting.h" > #include <stdio.h> > #include <wtf/text/StringBuilder.h> > #include <wtf/text/WTFString.h> >@@ -65,6 +66,7 @@ static void testSummaryProviders() > > int main(int argc, const char* argv[]) > { >+ avoidClassDeadStripping(); > testSummaryProviders(); > fprintf(stderr, "This executable does nothing and is only meant for debugging lldb_webkit.py.\n"); > return 0; >diff --git a/Tools/lldb/lldb_dump_class_layout.py b/Tools/lldb/lldb_dump_class_layout.py >new file mode 100755 >index 0000000000000000000000000000000000000000..638d9d4774fa0acd9276505221d3d16fab6ad605 >--- /dev/null >+++ b/Tools/lldb/lldb_dump_class_layout.py >@@ -0,0 +1,190 @@ >+#!/usr/bin/env python >+# -*- coding: utf-8 -*- >+# >+# Copyright (C) 2018 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 os >+import re >+import subprocess >+import sys >+from sets import Set >+ >+from webkitpy.common.system.systemhost import SystemHost >+sys.path.append(SystemHost().path_to_lldb_python_directory()) >+import lldb >+ >+ >+class ClassLayoutDumper: >+ "Dumps the class layout of a C++ class using the lldb python bindings." >+ >+ >+ def __init__(self, binary_path, classname, architecture): >+ self.binary_path = binary_path >+ self.classname = classname >+ self.architecture = architecture >+ >+ def _get_first_file_architecture(self): >+ p = re.compile('shared library +(\w+)$') >+ file_result = subprocess.check_output(["file", self.binary_path]).split('\n') >+ arches = [] >+ for line in file_result: >+ match = p.search(line) >+ if match: >+ arches.append(match.group(1)) >+ >+ if len(arches) > 1: >+ print 'Found architectures %s, using %s' % (arches, arches[0]) >+ >+ if len(arches) > 0: >+ return arches[0] >+ >+ return lldb.LLDB_ARCH_DEFAULT >+ >+ def verify_type(self, target, type, str_list): >+ typename = type.GetName() >+ seenOffset = Set() >+ (end_offset, padding) = self.verify_type_recursive(target, type, None, 0, 0, 0, seenOffset, str_list) >+ byte_size = type.GetByteSize() >+ str_list.append('Total byte size: %u' % (byte_size)) >+ str_list.append('Total pad bytes: %u' % (padding)) >+ if padding > 0: >+ str_list.append('Padding percentage: %2.2f %%' % ((float(padding) / float(byte_size)) * 100.0)) >+ str_list.append('') >+ >+ def verify_type_recursive(self, target, type, member_name, depth, base_offset, padding, seenOffset, str_list): >+ prev_end_offset = base_offset >+ typename = type.GetName() >+ byte_size = type.GetByteSize() >+ if member_name and member_name != typename: >+ str_list.append('%+4u <%3u> %s%s %s;' % (base_offset, byte_size, ' ' * depth, typename, member_name)) >+ else: >+ str_list.append('%+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_offset, member_name) in seenOffset: >+ continue >+ seenOffset.add((member_offset, member_name)) >+ >+ 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() >+ str_list.append('%+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 >+ str_list.append('%+4u <%3u> %s<PADDING>' % (prev_end_offset, member_padding, ' ' * (depth + 1))) >+ >+ if member_is_class_or_struct: >+ (prev_end_offset, padding) = self.verify_type_recursive(target, member_canonical_type, member_name, depth + 1, member_total_offset, padding, seenOffset, str_list) >+ else: >+ prev_end_offset = member_total_offset + member_byte_size >+ member_typename = member_type.GetName() >+ if member.IsBitfield(): >+ str_list.append('%+4u <%3u> %s%s:%u %s;' % (member_total_offset, member_byte_size, ' ' * (depth + 1), member_typename, member.GetBitfieldSizeInBits(), member_name)) >+ else: >+ str_list.append('%+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 >+ str_list.append('%+4u <%3u> %s<PADDING>' % (prev_end_offset, last_member_padding, ' ' * (depth + 1))) >+ padding += last_member_padding >+ else: >+ if type.IsPolymorphicClass(): >+ ptr_size = target.GetAddressByteSize() >+ str_list.append('%+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 _class_layout_as_string(self, target, type): >+ str_list = [] >+ self.verify_type(target, type, str_list) >+ return '\n'.join(str_list) >+ >+ def dump_to_string(self): >+ debugger = lldb.SBDebugger.Create() >+ debugger.SetAsync(False) >+ architecture = self.architecture >+ if not architecture: >+ architecture = self._get_first_file_architecture() >+ >+ target = debugger.CreateTargetWithFileAndArch(str(self.binary_path), architecture) >+ if not target: >+ return "Failed to make target for " + self.binary_path >+ >+ module = target.GetModuleAtIndex(0) >+ if not module: >+ return "Failed to get first module in " + self.binary_path >+ >+ result = "" >+ types = module.FindTypes(self.classname) >+ if types.GetSize(): >+ for type in types: >+ result += self._class_layout_as_string(target, type) >+ else: >+ result = 'error: no type matches "%s" in "%s"' % (self.classname, module.file) >+ >+ lldb.SBDebugger.Destroy(debugger) >+ return result >+ >+ def dump(self): >+ debugger = lldb.SBDebugger.Create() >+ debugger.SetAsync(False) >+ architecture = self.architecture >+ if not architecture: >+ architecture = self._get_first_file_architecture() >+ >+ target = debugger.CreateTargetWithFileAndArch(str(self.binary_path), architecture) >+ if not target: >+ print "Failed to make target for " + self.binary_path >+ sys.exit(1) >+ >+ module = target.GetModuleAtIndex(0) >+ if not module: >+ print "Failed to get first module in " + self.binary_path >+ sys.exit(1) >+ >+ types = module.FindTypes(self.classname) >+ if types.GetSize(): >+ print 'Found %u types matching "%s" in "%s" for %s' % (len(types), self.classname, module.file, architecture) >+ for type in types: >+ print self._class_layout_as_string(target, type) >+ else: >+ print 'error: no type matches "%s" in "%s"' % (self.classname, module.file) >+ >+ lldb.SBDebugger.Destroy(debugger)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
dbates
:
review+
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 187141
: 343809 |
343815