| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2012 the V8 project authors. All rights reserved. | 3 # Copyright 2012 the V8 project authors. All rights reserved. |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 HeapObject.__init__(self, heap, None, None) | 1614 HeapObject.__init__(self, heap, None, None) |
| 1615 self.instance_type = instance_type | 1615 self.instance_type = instance_type |
| 1616 self.known_name = known_name | 1616 self.known_name = known_name |
| 1617 | 1617 |
| 1618 def __str__(self): | 1618 def __str__(self): |
| 1619 return "<%s>" % self.known_name | 1619 return "<%s>" % self.known_name |
| 1620 | 1620 |
| 1621 | 1621 |
| 1622 COMMENT_RE = re.compile(r"^C (0x[0-9a-fA-F]+) (.*)$") | 1622 COMMENT_RE = re.compile(r"^C (0x[0-9a-fA-F]+) (.*)$") |
| 1623 PAGEADDRESS_RE = re.compile( | 1623 PAGEADDRESS_RE = re.compile( |
| 1624 r"^P (mappage|pointerpage|datapage) (0x[0-9a-fA-F]+)$") | 1624 r"^P (mappage|oldpage) (0x[0-9a-fA-F]+)$") |
| 1625 | 1625 |
| 1626 | 1626 |
| 1627 class InspectionInfo(object): | 1627 class InspectionInfo(object): |
| 1628 def __init__(self, minidump_name, reader): | 1628 def __init__(self, minidump_name, reader): |
| 1629 self.comment_file = minidump_name + ".comments" | 1629 self.comment_file = minidump_name + ".comments" |
| 1630 self.address_comments = {} | 1630 self.address_comments = {} |
| 1631 self.page_address = {} | 1631 self.page_address = {} |
| 1632 if os.path.exists(self.comment_file): | 1632 if os.path.exists(self.comment_file): |
| 1633 with open(self.comment_file, "r") as f: | 1633 with open(self.comment_file, "r") as f: |
| 1634 lines = f.readlines() | 1634 lines = f.readlines() |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1691 def get_comment(self, address): | 1691 def get_comment(self, address): |
| 1692 return self.address_comments.get(address, "") | 1692 return self.address_comments.get(address, "") |
| 1693 | 1693 |
| 1694 | 1694 |
| 1695 class InspectionPadawan(object): | 1695 class InspectionPadawan(object): |
| 1696 """The padawan can improve annotations by sensing well-known objects.""" | 1696 """The padawan can improve annotations by sensing well-known objects.""" |
| 1697 def __init__(self, reader, heap): | 1697 def __init__(self, reader, heap): |
| 1698 self.reader = reader | 1698 self.reader = reader |
| 1699 self.heap = heap | 1699 self.heap = heap |
| 1700 self.known_first_map_page = 0 | 1700 self.known_first_map_page = 0 |
| 1701 self.known_first_data_page = 0 | 1701 self.known_first_old_page = 0 |
| 1702 self.known_first_pointer_page = 0 | |
| 1703 | 1702 |
| 1704 def __getattr__(self, name): | 1703 def __getattr__(self, name): |
| 1705 """An InspectionPadawan can be used instead of V8Heap, even though | 1704 """An InspectionPadawan can be used instead of V8Heap, even though |
| 1706 it does not inherit from V8Heap (aka. mixin).""" | 1705 it does not inherit from V8Heap (aka. mixin).""" |
| 1707 return getattr(self.heap, name) | 1706 return getattr(self.heap, name) |
| 1708 | 1707 |
| 1709 def GetPageOffset(self, tagged_address): | 1708 def GetPageOffset(self, tagged_address): |
| 1710 return tagged_address & self.heap.PageAlignmentMask() | 1709 return tagged_address & self.heap.PageAlignmentMask() |
| 1711 | 1710 |
| 1712 def IsInKnownMapSpace(self, tagged_address): | 1711 def IsInKnownMapSpace(self, tagged_address): |
| 1713 page_address = tagged_address & ~self.heap.PageAlignmentMask() | 1712 page_address = tagged_address & ~self.heap.PageAlignmentMask() |
| 1714 return page_address == self.known_first_map_page | 1713 return page_address == self.known_first_map_page |
| 1715 | 1714 |
| 1716 def IsInKnownOldSpace(self, tagged_address): | 1715 def IsInKnownOldSpace(self, tagged_address): |
| 1717 page_address = tagged_address & ~self.heap.PageAlignmentMask() | 1716 page_address = tagged_address & ~self.heap.PageAlignmentMask() |
| 1718 return page_address in [self.known_first_data_page, | 1717 return page_address == self.known_first_old_page |
| 1719 self.known_first_pointer_page] | |
| 1720 | 1718 |
| 1721 def ContainingKnownOldSpaceName(self, tagged_address): | 1719 def ContainingKnownOldSpaceName(self, tagged_address): |
| 1722 page_address = tagged_address & ~self.heap.PageAlignmentMask() | 1720 page_address = tagged_address & ~self.heap.PageAlignmentMask() |
| 1723 if page_address == self.known_first_data_page: return "OLD_DATA_SPACE" | 1721 if page_address == self.known_first_old_page: return "OLD_SPACE" |
| 1724 if page_address == self.known_first_pointer_page: return "OLD_POINTER_SPACE" | |
| 1725 return None | 1722 return None |
| 1726 | 1723 |
| 1727 def SenseObject(self, tagged_address): | 1724 def SenseObject(self, tagged_address): |
| 1728 if self.IsInKnownOldSpace(tagged_address): | 1725 if self.IsInKnownOldSpace(tagged_address): |
| 1729 offset = self.GetPageOffset(tagged_address) | 1726 offset = self.GetPageOffset(tagged_address) |
| 1730 lookup_key = (self.ContainingKnownOldSpaceName(tagged_address), offset) | 1727 lookup_key = (self.ContainingKnownOldSpaceName(tagged_address), offset) |
| 1731 known_obj_name = KNOWN_OBJECTS.get(lookup_key) | 1728 known_obj_name = KNOWN_OBJECTS.get(lookup_key) |
| 1732 if known_obj_name: | 1729 if known_obj_name: |
| 1733 return KnownObject(self, known_obj_name) | 1730 return KnownObject(self, known_obj_name) |
| 1734 if self.IsInKnownMapSpace(tagged_address): | 1731 if self.IsInKnownMapSpace(tagged_address): |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1771 def FindObject(self, tagged_address): | 1768 def FindObject(self, tagged_address): |
| 1772 """When used as a mixin in place of V8Heap.""" | 1769 """When used as a mixin in place of V8Heap.""" |
| 1773 raise NotImplementedError | 1770 raise NotImplementedError |
| 1774 | 1771 |
| 1775 def FindMap(self, tagged_address): | 1772 def FindMap(self, tagged_address): |
| 1776 """When used as a mixin in place of V8Heap.""" | 1773 """When used as a mixin in place of V8Heap.""" |
| 1777 raise NotImplementedError | 1774 raise NotImplementedError |
| 1778 | 1775 |
| 1779 def PrintKnowledge(self): | 1776 def PrintKnowledge(self): |
| 1780 print " known_first_map_page = %s\n"\ | 1777 print " known_first_map_page = %s\n"\ |
| 1781 " known_first_data_page = %s\n"\ | 1778 " known_first_old_page = %s" % ( |
| 1782 " known_first_pointer_page = %s" % ( | |
| 1783 self.reader.FormatIntPtr(self.known_first_map_page), | 1779 self.reader.FormatIntPtr(self.known_first_map_page), |
| 1784 self.reader.FormatIntPtr(self.known_first_data_page), | 1780 self.reader.FormatIntPtr(self.known_first_old_page)) |
| 1785 self.reader.FormatIntPtr(self.known_first_pointer_page)) | |
| 1786 | 1781 |
| 1787 WEB_HEADER = """ | 1782 WEB_HEADER = """ |
| 1788 <!DOCTYPE html> | 1783 <!DOCTYPE html> |
| 1789 <html> | 1784 <html> |
| 1790 <head> | 1785 <head> |
| 1791 <meta content="text/html; charset=utf-8" http-equiv="content-type"> | 1786 <meta content="text/html; charset=utf-8" http-equiv="content-type"> |
| 1792 <style media="screen" type="text/css"> | 1787 <style media="screen" type="text/css"> |
| 1793 | 1788 |
| 1794 .code { | 1789 .code { |
| 1795 font-family: monospace; | 1790 font-family: monospace; |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2117 exception_thread.stack.memory.data_size | 2112 exception_thread.stack.memory.data_size |
| 2118 stack_map = {self.reader.ExceptionIP(): -1} | 2113 stack_map = {self.reader.ExceptionIP(): -1} |
| 2119 for slot in xrange(stack_top, stack_bottom, self.reader.PointerSize()): | 2114 for slot in xrange(stack_top, stack_bottom, self.reader.PointerSize()): |
| 2120 maybe_address = self.reader.ReadUIntPtr(slot) | 2115 maybe_address = self.reader.ReadUIntPtr(slot) |
| 2121 if not maybe_address in stack_map: | 2116 if not maybe_address in stack_map: |
| 2122 stack_map[maybe_address] = slot | 2117 stack_map[maybe_address] = slot |
| 2123 self.heap = V8Heap(self.reader, stack_map) | 2118 self.heap = V8Heap(self.reader, stack_map) |
| 2124 | 2119 |
| 2125 self.padawan = InspectionPadawan(self.reader, self.heap) | 2120 self.padawan = InspectionPadawan(self.reader, self.heap) |
| 2126 self.comments = InspectionInfo(minidump_name, self.reader) | 2121 self.comments = InspectionInfo(minidump_name, self.reader) |
| 2127 self.padawan.known_first_data_page = ( | 2122 self.padawan.known_first_old_page = ( |
| 2128 self.comments.get_page_address("datapage")) | 2123 self.comments.get_page_address("oldpage")) |
| 2129 self.padawan.known_first_map_page = ( | 2124 self.padawan.known_first_map_page = ( |
| 2130 self.comments.get_page_address("mappage")) | 2125 self.comments.get_page_address("mappage")) |
| 2131 self.padawan.known_first_pointer_page = ( | |
| 2132 self.comments.get_page_address("pointerpage")) | |
| 2133 | 2126 |
| 2134 def set_comment(self, straddress, comment): | 2127 def set_comment(self, straddress, comment): |
| 2135 try: | 2128 try: |
| 2136 address = int(straddress, 0) | 2129 address = int(straddress, 0) |
| 2137 self.comments.set_comment(address, comment) | 2130 self.comments.set_comment(address, comment) |
| 2138 except ValueError: | 2131 except ValueError: |
| 2139 print "Invalid address" | 2132 print "Invalid address" |
| 2140 | 2133 |
| 2141 def set_page_address(self, kind, straddress): | 2134 def set_page_address(self, kind, straddress): |
| 2142 try: | 2135 try: |
| 2143 address = int(straddress, 0) | 2136 address = int(straddress, 0) |
| 2144 if kind == "datapage": | 2137 if kind == "oldpage": |
| 2145 self.padawan.known_first_data_page = address | 2138 self.padawan.known_first_old_page = address |
| 2146 elif kind == "mappage": | 2139 elif kind == "mappage": |
| 2147 self.padawan.known_first_map_page = address | 2140 self.padawan.known_first_map_page = address |
| 2148 elif kind == "pointerpage": | |
| 2149 self.padawan.known_first_pointer_page = address | |
| 2150 self.comments.save_page_address(kind, address) | 2141 self.comments.save_page_address(kind, address) |
| 2151 except ValueError: | 2142 except ValueError: |
| 2152 print "Invalid address" | 2143 print "Invalid address" |
| 2153 | 2144 |
| 2154 def td_from_address(self, f, address): | 2145 def td_from_address(self, f, address): |
| 2155 f.write("<td %s>" % self.comments.get_style_class_string(address)) | 2146 f.write("<td %s>" % self.comments.get_style_class_string(address)) |
| 2156 | 2147 |
| 2157 def format_address(self, maybeaddress, straddress = None): | 2148 def format_address(self, maybeaddress, straddress = None): |
| 2158 if maybeaddress is None: | 2149 if maybeaddress is None: |
| 2159 return "not in dump" | 2150 return "not in dump" |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 | 2601 |
| 2611 address = int(straddress, 0) | 2602 address = int(straddress, 0) |
| 2612 | 2603 |
| 2613 f.write("Comment: ") | 2604 f.write("Comment: ") |
| 2614 self.output_comment_box(f, "search-", address) | 2605 self.output_comment_box(f, "search-", address) |
| 2615 f.write("<br>\n") | 2606 f.write("<br>\n") |
| 2616 | 2607 |
| 2617 page_address = address & ~self.heap.PageAlignmentMask() | 2608 page_address = address & ~self.heap.PageAlignmentMask() |
| 2618 | 2609 |
| 2619 f.write("Page info: \n") | 2610 f.write("Page info: \n") |
| 2620 self.output_page_info(f, "data", self.padawan.known_first_data_page, \ | 2611 self.output_page_info(f, "old", self.padawan.known_first_old_page, \ |
| 2621 page_address) | 2612 page_address) |
| 2622 self.output_page_info(f, "map", self.padawan.known_first_map_page, \ | 2613 self.output_page_info(f, "map", self.padawan.known_first_map_page, \ |
| 2623 page_address) | 2614 page_address) |
| 2624 self.output_page_info(f, "pointer", \ | |
| 2625 self.padawan.known_first_pointer_page, \ | |
| 2626 page_address) | |
| 2627 | 2615 |
| 2628 if not self.reader.IsValidAddress(address): | 2616 if not self.reader.IsValidAddress(address): |
| 2629 f.write("<h3>The contents at address %s not found in the dump.</h3>" % \ | 2617 f.write("<h3>The contents at address %s not found in the dump.</h3>" % \ |
| 2630 straddress) | 2618 straddress) |
| 2631 else: | 2619 else: |
| 2632 # Print as words | 2620 # Print as words |
| 2633 self.output_words(f, address - 8, address + 32, address, "Dump") | 2621 self.output_words(f, address - 8, address + 32, address, "Dump") |
| 2634 | 2622 |
| 2635 # Print as ASCII | 2623 # Print as ASCII |
| 2636 f.write("<hr>\n") | 2624 f.write("<hr>\n") |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2918 | 2906 |
| 2919 def do_k(self, arguments): | 2907 def do_k(self, arguments): |
| 2920 """ | 2908 """ |
| 2921 Teach V8 heap layout information to the inspector. This increases | 2909 Teach V8 heap layout information to the inspector. This increases |
| 2922 the amount of annotations the inspector can produce while dumping | 2910 the amount of annotations the inspector can produce while dumping |
| 2923 data. The first page of each heap space is of particular interest | 2911 data. The first page of each heap space is of particular interest |
| 2924 because it contains known objects that do not move. | 2912 because it contains known objects that do not move. |
| 2925 """ | 2913 """ |
| 2926 self.padawan.PrintKnowledge() | 2914 self.padawan.PrintKnowledge() |
| 2927 | 2915 |
| 2928 def do_kd(self, address): | 2916 def do_ko(self, address): |
| 2929 """ | 2917 """ |
| 2930 Teach V8 heap layout information to the inspector. Set the first | 2918 Teach V8 heap layout information to the inspector. Set the first |
| 2931 data-space page by passing any pointer into that page. | 2919 old space page by passing any pointer into that page. |
| 2932 """ | 2920 """ |
| 2933 address = int(address, 16) | 2921 address = int(address, 16) |
| 2934 page_address = address & ~self.heap.PageAlignmentMask() | 2922 page_address = address & ~self.heap.PageAlignmentMask() |
| 2935 self.padawan.known_first_data_page = page_address | 2923 self.padawan.known_first_old_page = page_address |
| 2936 | 2924 |
| 2937 def do_km(self, address): | 2925 def do_km(self, address): |
| 2938 """ | 2926 """ |
| 2939 Teach V8 heap layout information to the inspector. Set the first | 2927 Teach V8 heap layout information to the inspector. Set the first |
| 2940 map-space page by passing any pointer into that page. | 2928 map-space page by passing any pointer into that page. |
| 2941 """ | 2929 """ |
| 2942 address = int(address, 16) | 2930 address = int(address, 16) |
| 2943 page_address = address & ~self.heap.PageAlignmentMask() | 2931 page_address = address & ~self.heap.PageAlignmentMask() |
| 2944 self.padawan.known_first_map_page = page_address | 2932 self.padawan.known_first_map_page = page_address |
| 2945 | 2933 |
| 2946 def do_kp(self, address): | |
| 2947 """ | |
| 2948 Teach V8 heap layout information to the inspector. Set the first | |
| 2949 pointer-space page by passing any pointer into that page. | |
| 2950 """ | |
| 2951 address = int(address, 16) | |
| 2952 page_address = address & ~self.heap.PageAlignmentMask() | |
| 2953 self.padawan.known_first_pointer_page = page_address | |
| 2954 | |
| 2955 def do_list(self, smth): | 2934 def do_list(self, smth): |
| 2956 """ | 2935 """ |
| 2957 List all available memory regions. | 2936 List all available memory regions. |
| 2958 """ | 2937 """ |
| 2959 def print_region(reader, start, size, location): | 2938 def print_region(reader, start, size, location): |
| 2960 print " %s - %s (%d bytes)" % (reader.FormatIntPtr(start), | 2939 print " %s - %s (%d bytes)" % (reader.FormatIntPtr(start), |
| 2961 reader.FormatIntPtr(start + size), | 2940 reader.FormatIntPtr(start + size), |
| 2962 size) | 2941 size) |
| 2963 print "Available memory regions:" | 2942 print "Available memory regions:" |
| 2964 self.reader.ForEachMemoryRegion(print_region) | 2943 self.reader.ForEachMemoryRegion(print_region) |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3185 try: | 3164 try: |
| 3186 server = InspectionWebServer(PORT_NUMBER, options, args[0]) | 3165 server = InspectionWebServer(PORT_NUMBER, options, args[0]) |
| 3187 print 'Started httpserver on port ' , PORT_NUMBER | 3166 print 'Started httpserver on port ' , PORT_NUMBER |
| 3188 webbrowser.open('http://localhost:%i/summary.html' % PORT_NUMBER) | 3167 webbrowser.open('http://localhost:%i/summary.html' % PORT_NUMBER) |
| 3189 server.serve_forever() | 3168 server.serve_forever() |
| 3190 except KeyboardInterrupt: | 3169 except KeyboardInterrupt: |
| 3191 print '^C received, shutting down the web server' | 3170 print '^C received, shutting down the web server' |
| 3192 server.socket.close() | 3171 server.socket.close() |
| 3193 else: | 3172 else: |
| 3194 AnalyzeMinidump(options, args[0]) | 3173 AnalyzeMinidump(options, args[0]) |
| OLD | NEW |