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 |