Alter Tools/Scripts/dump-class-layout to be able to dump all classes with suspicious...
authorrmorisset@apple.com <rmorisset@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 20:55:49 +0000 (20:55 +0000)
committerrmorisset@apple.com <rmorisset@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 20:55:49 +0000 (20:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195573

Reviewed by Simon Fraser.

Also modified the script so that when multiple types match a given name it shows them all and not arbitrarily pick one.

* Scripts/dump-class-layout:
(main):
* lldb/lldb_dump_class_layout.py:
(ClassLayout.__init__):
(ClassLayout._compute_padding_recursive):
(LLDBDebuggerInstance.dump_layout_for_classname):
(LLDBDebuggerInstance):
(LLDBDebuggerInstance.dump_all_wasteful_layouts):
(LLDBDebuggerInstance.layout_for_classname): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242825 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/dump-class-layout
Tools/lldb/lldb_dump_class_layout.py

index c4cda3b..e35b6cd 100644 (file)
@@ -1,3 +1,22 @@
+2019-03-12  Robin Morisset  <rmorisset@apple.com>
+
+        Alter Tools/Scripts/dump-class-layout to be able to dump all classes with suspicious padding
+        https://bugs.webkit.org/show_bug.cgi?id=195573
+
+        Reviewed by Simon Fraser.
+
+        Also modified the script so that when multiple types match a given name it shows them all and not arbitrarily pick one.
+
+        * Scripts/dump-class-layout:
+        (main):
+        * lldb/lldb_dump_class_layout.py:
+        (ClassLayout.__init__):
+        (ClassLayout._compute_padding_recursive):
+        (LLDBDebuggerInstance.dump_layout_for_classname):
+        (LLDBDebuggerInstance):
+        (LLDBDebuggerInstance.dump_all_wasteful_layouts):
+        (LLDBDebuggerInstance.layout_for_classname): Deleted.
+
 2019-03-12  Chris Dumez  <cdumez@apple.com>
 
         Device Orientation access permission should be denied unless explicitly granted by the client
index a547e20..df943cc 100755 (executable)
@@ -51,7 +51,7 @@ 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',
+    parser.add_argument('classname', metavar='classname', nargs='?',
         help='name of the class or struct to dump')
 
     parser.add_argument('-b', '--build-directory', dest='build_directory', action='store',
@@ -66,6 +66,9 @@ def main():
     parser.add_argument('-t', '--target-path', dest='target_path', action='store',
         help='Path to the target')
 
+    parser.add_argument('-w', '--all-wasteful', dest='all_wasteful', action='store_true',
+        help='Exclusive with classname, dumps the layout of all classes with at least 8 bytes of padding at the top-level')
+
     args = parser.parse_args()
     build_dir = webkit_build_dir()
 
@@ -81,9 +84,14 @@ def main():
         target_path = os.path.join(build_dir, args.config, args.framework + ".framework", args.framework);
     
     lldb_instance = LLDBDebuggerInstance(target_path, args.arch)
-    class_layout = lldb_instance.layout_for_classname(args.classname)
-    class_layout.dump()
-
+    if args.all_wasteful and (args.classname is not None):
+        print "The -w/--all-wasteful option is incompatible with providing a class name"
+    elif args.all_wasteful:
+        lldb_instance.dump_all_wasteful_layouts()
+    elif args.classname is not None:
+        lldb_instance.dump_layout_for_classname(args.classname)
+    else:
+        print "You must either provide a class name or the -w/--all-wasteful option"
 
 if __name__ == "__main__":
     main()
index 3bebf8f..360a184 100755 (executable)
@@ -145,6 +145,7 @@ class ClassLayout(ClassLayoutBase):
         self.total_byte_size = self.type.GetByteSize()
         self.pointer_size = self.target.GetAddressByteSize()
         self.total_pad_bytes = 0
+        self.top_level_pad_bytes = 0
         self.data_members = []
         self.virtual_base_classes = self._virtual_base_classes_dictionary()
         self._parse(containerClass, derivedClass)
@@ -319,6 +320,8 @@ class ClassLayout(ClassLayoutBase):
 
                     self.data_members.insert(i, padding_member)
                     padding_bytes += padding_size
+                    if depth == 0 and padding_size < 8:
+                        self.top_level_pad_bytes += padding_size
                     i += 1
 
                 if self.MEMBER_IS_BITFIELD in data_member:
@@ -364,6 +367,7 @@ class ClassLayout(ClassLayoutBase):
                 }
                 self.data_members.append(padding_member)
                 padding_bytes += padding_size
+                self.top_level_pad_bytes += padding_size
 
         return [padding_bytes, current_offset]
 
@@ -411,11 +415,22 @@ class LLDBDebuggerInstance:
 
         return lldb.LLDB_ARCH_DEFAULT
 
-    def layout_for_classname(self, classname):
+    def dump_layout_for_classname(self, classname):
         types = self.module.FindTypes(classname)
-        if types.GetSize():
-            # There can be more that one type with a given name, but for now just return the first one.
-            return ClassLayout(self.target, types.GetTypeAtIndex(0))
-
-        print 'error: no type matches "%s" in "%s"' % (classname, self.module.file)
-        return None
+        if not types.GetSize():
+            print 'error: no type matches "%s" in "%s"' % (classname, self.module.file)
+            return None
+        for t in types:
+            ClassLayout(self.target, t).dump()
+
+    def dump_all_wasteful_layouts(self):
+        types = self.module.GetTypes(lldb.eTypeClassClass | lldb.eTypeClassStruct)
+        seenTypes = set()
+        for t in types:
+            if t.GetName() in seenTypes:
+                continue
+            seenTypes.add(t.GetName())
+            classLayout = ClassLayout(self.target, t)
+            if classLayout.top_level_pad_bytes >= 8:
+                classLayout.dump()
+                print ""