Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: tools/grokdump.py

Issue 10441088: Implement grokdump annotations for well-known objects. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comment by Erik Corry. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2011 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
11 # copyright notice, this list of conditions and the following 11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided 12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution. 13 # with the distribution.
(...skipping 19 matching lines...) Expand all
33 import optparse 33 import optparse
34 import os 34 import os
35 import disasm 35 import disasm
36 import sys 36 import sys
37 import types 37 import types
38 import codecs 38 import codecs
39 import re 39 import re
40 import struct 40 import struct
41 41
42 42
43 USAGE="""usage: %prog [OPTION]... 43 USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
44 44
45 Minidump analyzer. 45 Minidump analyzer.
46 46
47 Shows the processor state at the point of exception including the 47 Shows the processor state at the point of exception including the
48 stack of the active thread and the referenced objects in the V8 48 stack of the active thread and the referenced objects in the V8
49 heap. Code objects are disassembled and the addresses linked from the 49 heap. Code objects are disassembled and the addresses linked from the
50 stack (pushed return addresses) are marked with "=>". 50 stack (e.g. pushed return addresses) are marked with "=>".
51
52 51
53 Examples: 52 Examples:
54 $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp 53 $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp"""
55 """
56 54
57 55
58 DEBUG=False 56 DEBUG=False
59 57
60 58
61 def DebugPrint(s): 59 def DebugPrint(s):
62 if not DEBUG: return 60 if not DEBUG: return
63 print s 61 print s
64 62
65 63
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 class Raw(ctypes.Structure): 99 class Raw(ctypes.Structure):
102 _fields_ = fields 100 _fields_ = fields
103 _pack_ = 1 101 _pack_ = 1
104 102
105 def __str__(self): 103 def __str__(self):
106 return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field)) 104 return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field))
107 for field, _ in Raw._fields_) + "}" 105 for field, _ in Raw._fields_) + "}"
108 return Raw 106 return Raw
109 107
110 108
111 def do_dump(reader, heap): 109 def FullDump(reader, heap):
112 """Dump all available memory regions.""" 110 """Dump all available memory regions."""
113 def dump_region(reader, start, size, location): 111 def dump_region(reader, start, size, location):
114 print 112 print
115 while start & 3 != 0: 113 while start & 3 != 0:
116 start += 1 114 start += 1
117 size -= 1 115 size -= 1
118 location += 1 116 location += 1
119 is_executable = reader.IsProbableExecutableRegion(location, size) 117 is_executable = reader.IsProbableExecutableRegion(location, size)
120 is_ascii = reader.IsProbableASCIIRegion(location, size) 118 is_ascii = reader.IsProbableASCIIRegion(location, size)
121 119
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 """Minidump (.dmp) reader.""" 411 """Minidump (.dmp) reader."""
414 412
415 _HEADER_MAGIC = 0x504d444d 413 _HEADER_MAGIC = 0x504d444d
416 414
417 def __init__(self, options, minidump_name): 415 def __init__(self, options, minidump_name):
418 self.minidump_name = minidump_name 416 self.minidump_name = minidump_name
419 self.minidump_file = open(minidump_name, "r") 417 self.minidump_file = open(minidump_name, "r")
420 self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE) 418 self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE)
421 self.header = MINIDUMP_HEADER.Read(self.minidump, 0) 419 self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
422 if self.header.signature != MinidumpReader._HEADER_MAGIC: 420 if self.header.signature != MinidumpReader._HEADER_MAGIC:
423 print >>sys.stderr, "Warning: unsupported minidump header magic" 421 print >>sys.stderr, "Warning: Unsupported minidump header magic!"
424 DebugPrint(self.header) 422 DebugPrint(self.header)
425 directories = [] 423 directories = []
426 offset = self.header.stream_directories_rva 424 offset = self.header.stream_directories_rva
427 for _ in xrange(self.header.stream_count): 425 for _ in xrange(self.header.stream_count):
428 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset)) 426 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset))
429 offset += MINIDUMP_DIRECTORY.size 427 offset += MINIDUMP_DIRECTORY.size
430 self.arch = None 428 self.arch = None
431 self.exception = None 429 self.exception = None
432 self.exception_context = None 430 self.exception_context = None
433 self.memory_list = None 431 self.memory_list = None
(...skipping 23 matching lines...) Expand all
457 self.minidump, self.exception.thread_context.rva) 455 self.minidump, self.exception.thread_context.rva)
458 DebugPrint(self.exception_context) 456 DebugPrint(self.exception_context)
459 elif d.stream_type == MD_THREAD_LIST_STREAM: 457 elif d.stream_type == MD_THREAD_LIST_STREAM:
460 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) 458 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
461 assert ctypes.sizeof(thread_list) == d.location.data_size 459 assert ctypes.sizeof(thread_list) == d.location.data_size
462 DebugPrint(thread_list) 460 DebugPrint(thread_list)
463 for thread in thread_list.threads: 461 for thread in thread_list.threads:
464 DebugPrint(thread) 462 DebugPrint(thread)
465 self.thread_map[thread.id] = thread 463 self.thread_map[thread.id] = thread
466 elif d.stream_type == MD_MEMORY_LIST_STREAM: 464 elif d.stream_type == MD_MEMORY_LIST_STREAM:
467 print >>sys.stderr, "Warning: not a full minidump" 465 print >>sys.stderr, "Warning: This is not a full minidump!"
468 assert self.memory_list is None 466 assert self.memory_list is None
469 self.memory_list = MINIDUMP_MEMORY_LIST.Read( 467 self.memory_list = MINIDUMP_MEMORY_LIST.Read(
470 self.minidump, d.location.rva) 468 self.minidump, d.location.rva)
471 assert ctypes.sizeof(self.memory_list) == d.location.data_size 469 assert ctypes.sizeof(self.memory_list) == d.location.data_size
472 DebugPrint(self.memory_list) 470 DebugPrint(self.memory_list)
473 elif d.stream_type == MD_MEMORY_64_LIST_STREAM: 471 elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
474 assert self.memory_list64 is None 472 assert self.memory_list64 is None
475 self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read( 473 self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read(
476 self.minidump, d.location.rva) 474 self.minidump, d.location.rva)
477 assert ctypes.sizeof(self.memory_list64) == d.location.data_size 475 assert ctypes.sizeof(self.memory_list64) == d.location.data_size
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 if self.memory_list64 is not None: 568 if self.memory_list64 is not None:
571 for r in self.memory_list64.ranges: 569 for r in self.memory_list64.ranges:
572 location = self.memory_list64.base_rva + offset 570 location = self.memory_list64.base_rva + offset
573 cb(self, r.start, r.size, location) 571 cb(self, r.start, r.size, location)
574 offset += r.size 572 offset += r.size
575 573
576 if self.memory_list is not None: 574 if self.memory_list is not None:
577 for r in self.memory_list.ranges: 575 for r in self.memory_list.ranges:
578 cb(self, r.start, r.memory.data_size, r.memory.rva) 576 cb(self, r.start, r.memory.data_size, r.memory.rva)
579 577
580 def FindWord(self, word): 578 def FindWord(self, word, alignment=0):
581 def search_inside_region(reader, start, size, location): 579 def search_inside_region(reader, start, size, location):
582 for loc in xrange(location, location + size): 580 location = (location + alignment) & ~alignment
581 for loc in xrange(location, location + size - self.PointerSize()):
583 if reader._ReadWord(loc) == word: 582 if reader._ReadWord(loc) == word:
584 slot = start + (loc - location) 583 slot = start + (loc - location)
585 print "%s: %s" % (reader.FormatIntPtr(slot), 584 print "%s: %s" % (reader.FormatIntPtr(slot),
586 reader.FormatIntPtr(word)) 585 reader.FormatIntPtr(word))
587
588 self.ForEachMemoryRegion(search_inside_region) 586 self.ForEachMemoryRegion(search_inside_region)
589 587
590 def FindLocation(self, address): 588 def FindLocation(self, address):
591 offset = 0 589 offset = 0
592 if self.memory_list64 is not None: 590 if self.memory_list64 is not None:
593 for r in self.memory_list64.ranges: 591 for r in self.memory_list64.ranges:
594 if r.start <= address < r.start + r.size: 592 if r.start <= address < r.start + r.size:
595 return self.memory_list64.base_rva + offset + address - r.start 593 return self.memory_list64.base_rva + offset + address - r.start
596 offset += r.size 594 offset += r.size
597 if self.memory_list is not None: 595 if self.memory_list is not None:
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 149: "ACCESS_CHECK_INFO_TYPE", 701 149: "ACCESS_CHECK_INFO_TYPE",
704 150: "INTERCEPTOR_INFO_TYPE", 702 150: "INTERCEPTOR_INFO_TYPE",
705 151: "CALL_HANDLER_INFO_TYPE", 703 151: "CALL_HANDLER_INFO_TYPE",
706 152: "FUNCTION_TEMPLATE_INFO_TYPE", 704 152: "FUNCTION_TEMPLATE_INFO_TYPE",
707 153: "OBJECT_TEMPLATE_INFO_TYPE", 705 153: "OBJECT_TEMPLATE_INFO_TYPE",
708 154: "SIGNATURE_INFO_TYPE", 706 154: "SIGNATURE_INFO_TYPE",
709 155: "TYPE_SWITCH_INFO_TYPE", 707 155: "TYPE_SWITCH_INFO_TYPE",
710 156: "SCRIPT_TYPE", 708 156: "SCRIPT_TYPE",
711 157: "CODE_CACHE_TYPE", 709 157: "CODE_CACHE_TYPE",
712 158: "POLYMORPHIC_CODE_CACHE_TYPE", 710 158: "POLYMORPHIC_CODE_CACHE_TYPE",
713 161: "FIXED_ARRAY_TYPE", 711 159: "TYPE_FEEDBACK_INFO_TYPE",
712 160: "ALIASED_ARGUMENTS_ENTRY_TYPE",
713 163: "FIXED_ARRAY_TYPE",
714 145: "FIXED_DOUBLE_ARRAY_TYPE", 714 145: "FIXED_DOUBLE_ARRAY_TYPE",
715 162: "SHARED_FUNCTION_INFO_TYPE", 715 164: "SHARED_FUNCTION_INFO_TYPE",
716 163: "JS_MESSAGE_OBJECT_TYPE", 716 165: "JS_MESSAGE_OBJECT_TYPE",
717 166: "JS_VALUE_TYPE", 717 168: "JS_VALUE_TYPE",
718 167: "JS_OBJECT_TYPE", 718 169: "JS_DATE_TYPE",
719 168: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", 719 170: "JS_OBJECT_TYPE",
720 169: "JS_GLOBAL_OBJECT_TYPE", 720 171: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
721 170: "JS_BUILTINS_OBJECT_TYPE", 721 172: "JS_MODULE_TYPE",
722 171: "JS_GLOBAL_PROXY_TYPE", 722 173: "JS_GLOBAL_OBJECT_TYPE",
723 172: "JS_ARRAY_TYPE", 723 174: "JS_BUILTINS_OBJECT_TYPE",
724 165: "JS_PROXY_TYPE", 724 175: "JS_GLOBAL_PROXY_TYPE",
725 175: "JS_WEAK_MAP_TYPE", 725 176: "JS_ARRAY_TYPE",
726 176: "JS_REGEXP_TYPE", 726 167: "JS_PROXY_TYPE",
727 177: "JS_FUNCTION_TYPE", 727 179: "JS_WEAK_MAP_TYPE",
728 164: "JS_FUNCTION_PROXY_TYPE", 728 180: "JS_REGEXP_TYPE",
729 159: "DEBUG_INFO_TYPE", 729 181: "JS_FUNCTION_TYPE",
730 160: "BREAK_POINT_INFO_TYPE", 730 166: "JS_FUNCTION_PROXY_TYPE",
731 161: "DEBUG_INFO_TYPE",
732 162: "BREAK_POINT_INFO_TYPE",
731 } 733 }
732 734
733 735
736 # List of known V8 maps. Used to determine the instance type and name
737 # for maps that are part of the root-set and hence on the first page of
738 # the map-space. Obtained by adding the code below to an IA32 release
739 # build with enabled snapshots to the end of the Isolate::Init method.
740 #
741 # #define ROOT_LIST_CASE(type, name, camel_name) \
Vitaly Repeshko 2012/05/31 17:34:20 Updating this stuff is going to be even more painf
Michael Starzinger 2012/06/01 09:13:06 Yes, I totally agree. At some point the build syst
742 # if (o == heap_.name()) n = #camel_name;
743 # #define STRUCT_LIST_CASE(upper_name, camel_name, name) \
744 # if (o == heap_.name##_map()) n = #camel_name "Map";
745 # HeapObjectIterator it(heap_.map_space());
746 # printf("KNOWN_MAPS = {\n");
747 # for (Object* o = it.Next(); o != NULL; o = it.Next()) {
748 # Map* m = Map::cast(o);
749 # const char* n = "";
750 # intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
751 # int t = m->instance_type();
752 # ROOT_LIST(ROOT_LIST_CASE)
753 # STRUCT_LIST(STRUCT_LIST_CASE)
754 # printf(" 0x%05x: (%d, \"%s\"),\n", p, t, n);
755 # }
756 # printf("}\n");
757 KNOWN_MAPS = {
758 0x08081: (134, "ByteArrayMap"),
759 0x080a1: (128, "MetaMap"),
760 0x080c1: (130, "OddballMap"),
761 0x080e1: (163, "FixedArrayMap"),
762 0x08101: (68, "AsciiSymbolMap"),
763 0x08121: (132, "HeapNumberMap"),
764 0x08141: (135, "FreeSpaceMap"),
765 0x08161: (146, "OnePointerFillerMap"),
766 0x08181: (146, "TwoPointerFillerMap"),
767 0x081a1: (131, "GlobalPropertyCellMap"),
768 0x081c1: (164, "SharedFunctionInfoMap"),
769 0x081e1: (4, "AsciiStringMap"),
770 0x08201: (163, "GlobalContextMap"),
771 0x08221: (129, "CodeMap"),
772 0x08241: (163, "ScopeInfoMap"),
773 0x08261: (163, "FixedCOWArrayMap"),
774 0x08281: (145, "FixedDoubleArrayMap"),
775 0x082a1: (163, "HashTableMap"),
776 0x082c1: (0, "StringMap"),
777 0x082e1: (64, "SymbolMap"),
778 0x08301: (1, "ConsStringMap"),
779 0x08321: (5, "ConsAsciiStringMap"),
780 0x08341: (3, "SlicedStringMap"),
781 0x08361: (7, "SlicedAsciiStringMap"),
782 0x08381: (65, "ConsSymbolMap"),
783 0x083a1: (69, "ConsAsciiSymbolMap"),
784 0x083c1: (66, "ExternalSymbolMap"),
785 0x083e1: (74, "ExternalSymbolWithAsciiDataMap"),
786 0x08401: (70, "ExternalAsciiSymbolMap"),
787 0x08421: (2, "ExternalStringMap"),
788 0x08441: (10, "ExternalStringWithAsciiDataMap"),
789 0x08461: (6, "ExternalAsciiStringMap"),
790 0x08481: (82, "ShortExternalSymbolMap"),
791 0x084a1: (90, "ShortExternalSymbolWithAsciiDataMap"),
792 0x084c1: (86, "ShortExternalAsciiSymbolMap"),
793 0x084e1: (18, "ShortExternalStringMap"),
794 0x08501: (26, "ShortExternalStringWithAsciiDataMap"),
795 0x08521: (22, "ShortExternalAsciiStringMap"),
796 0x08541: (0, "UndetectableStringMap"),
797 0x08561: (4, "UndetectableAsciiStringMap"),
798 0x08581: (144, "ExternalPixelArrayMap"),
799 0x085a1: (136, "ExternalByteArrayMap"),
800 0x085c1: (137, "ExternalUnsignedByteArrayMap"),
801 0x085e1: (138, "ExternalShortArrayMap"),
802 0x08601: (139, "ExternalUnsignedShortArrayMap"),
803 0x08621: (140, "ExternalIntArrayMap"),
804 0x08641: (141, "ExternalUnsignedIntArrayMap"),
805 0x08661: (142, "ExternalFloatArrayMap"),
806 0x08681: (143, "ExternalDoubleArrayMap"),
807 0x086a1: (163, "NonStrictArgumentsElementsMap"),
808 0x086c1: (163, "FunctionContextMap"),
809 0x086e1: (163, "CatchContextMap"),
810 0x08701: (163, "WithContextMap"),
811 0x08721: (163, "BlockContextMap"),
812 0x08741: (163, "ModuleContextMap"),
813 0x08761: (165, "JSMessageObjectMap"),
814 0x08781: (133, "ForeignMap"),
815 0x087a1: (170, "NeanderMap"),
816 0x087c1: (158, "PolymorphicCodeCacheMap"),
817 0x087e1: (156, "ScriptMap"),
818 0x08801: (147, "AccessorInfoMap"),
819 0x08821: (148, "AccessorPairMap"),
820 0x08841: (149, "AccessCheckInfoMap"),
821 0x08861: (150, "InterceptorInfoMap"),
822 0x08881: (151, "CallHandlerInfoMap"),
823 0x088a1: (152, "FunctionTemplateInfoMap"),
824 0x088c1: (153, "ObjectTemplateInfoMap"),
825 0x088e1: (154, "SignatureInfoMap"),
826 0x08901: (155, "TypeSwitchInfoMap"),
827 0x08921: (157, "CodeCacheMap"),
828 0x08941: (159, "TypeFeedbackInfoMap"),
829 0x08961: (160, "AliasedArgumentsEntryMap"),
830 0x08981: (161, "DebugInfoMap"),
831 0x089a1: (162, "BreakPointInfoMap"),
832 }
833
834
835 # List of known V8 objects. Used to determine name for objects that are
836 # part of the root-set and hence on the first page of various old-space
837 # paged. Obtained by adding the code below to an IA32 release build with
838 # enabled snapshots to the end of the Isolate::Init method.
839 #
840 # #define ROOT_LIST_CASE(type, name, camel_name) \
841 # if (o == heap_.name()) n = #camel_name;
842 # OldSpaces spit;
843 # printf("KNOWN_OBJECTS = {\n");
844 # for (PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
845 # HeapObjectIterator it(s);
846 # const char* sname = AllocationSpaceName(s->identity());
847 # for (Object* o = it.Next(); o != NULL; o = it.Next()) {
848 # const char* n = NULL;
849 # intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
850 # ROOT_LIST(ROOT_LIST_CASE)
851 # if (n != NULL) {
852 # printf(" (\"%s\", 0x%05x): \"%s\",\n", sname, p, n);
853 # }
854 # }
855 # }
856 # printf("}\n");
857 KNOWN_OBJECTS = {
858 ("OLD_POINTER_SPACE", 0x08081): "NullValue",
859 ("OLD_POINTER_SPACE", 0x08091): "UndefinedValue",
860 ("OLD_POINTER_SPACE", 0x080a1): "InstanceofCacheMap",
861 ("OLD_POINTER_SPACE", 0x080b1): "TrueValue",
862 ("OLD_POINTER_SPACE", 0x080c1): "FalseValue",
863 ("OLD_POINTER_SPACE", 0x080d1): "NoInterceptorResultSentinel",
864 ("OLD_POINTER_SPACE", 0x080e1): "ArgumentsMarker",
865 ("OLD_POINTER_SPACE", 0x080f1): "NumberStringCache",
866 ("OLD_POINTER_SPACE", 0x088f9): "SingleCharacterStringCache",
867 ("OLD_POINTER_SPACE", 0x08b01): "StringSplitCache",
868 ("OLD_POINTER_SPACE", 0x08f09): "TerminationException",
869 ("OLD_POINTER_SPACE", 0x08f19): "MessageListeners",
870 ("OLD_POINTER_SPACE", 0x08f35): "CodeStubs",
871 ("OLD_POINTER_SPACE", 0x09b61): "NonMonomorphicCache",
872 ("OLD_POINTER_SPACE", 0x0a175): "PolymorphicCodeCache",
873 ("OLD_POINTER_SPACE", 0x0a17d): "NativesSourceCache",
874 ("OLD_POINTER_SPACE", 0x0a1bd): "EmptyScript",
875 ("OLD_POINTER_SPACE", 0x0a1f9): "IntrinsicFunctionNames",
876 ("OLD_POINTER_SPACE", 0x24a49): "SymbolTable",
877 ("OLD_DATA_SPACE", 0x08081): "EmptyFixedArray",
878 ("OLD_DATA_SPACE", 0x080a1): "NanValue",
879 ("OLD_DATA_SPACE", 0x0811d): "EmptyByteArray",
880 ("OLD_DATA_SPACE", 0x08125): "EmptyString",
881 ("OLD_DATA_SPACE", 0x08131): "EmptyDescriptorArray",
882 ("OLD_DATA_SPACE", 0x08259): "InfinityValue",
883 ("OLD_DATA_SPACE", 0x08265): "MinusZeroValue",
884 ("OLD_DATA_SPACE", 0x08271): "PrototypeAccessors",
885 ("CODE_SPACE", 0x12b81): "JsEntryCode",
886 ("CODE_SPACE", 0x12c61): "JsConstructEntryCode",
887 }
888
889
734 class Printer(object): 890 class Printer(object):
735 """Printer with indentation support.""" 891 """Printer with indentation support."""
736 892
737 def __init__(self): 893 def __init__(self):
738 self.indent = 0 894 self.indent = 0
739 895
740 def Indent(self): 896 def Indent(self):
741 self.indent += 2 897 self.indent += 2
742 898
743 def Dedent(self): 899 def Dedent(self):
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 return self.heap.PointerSize() 1055 return self.heap.PointerSize()
900 1056
901 def __init__(self, heap, map, address): 1057 def __init__(self, heap, map, address):
902 HeapObject.__init__(self, heap, map, address) 1058 HeapObject.__init__(self, heap, map, address)
903 self.to_string = self.ObjectField(self.ToStringOffset()) 1059 self.to_string = self.ObjectField(self.ToStringOffset())
904 1060
905 def Print(self, p): 1061 def Print(self, p):
906 p.Print(str(self)) 1062 p.Print(str(self))
907 1063
908 def __str__(self): 1064 def __str__(self):
909 return "<%s>" % self.to_string.GetChars() 1065 if self.to_string:
1066 return "Oddball(%08x, <%s>)" % (self.address, self.to_string.GetChars())
1067 else:
1068 return "Oddball(%08x, kind=%s)" % (self.address, "???")
910 1069
911 1070
912 class FixedArray(HeapObject): 1071 class FixedArray(HeapObject):
913 def LengthOffset(self): 1072 def LengthOffset(self):
914 return self.heap.PointerSize() 1073 return self.heap.PointerSize()
915 1074
916 def ElementsOffset(self): 1075 def ElementsOffset(self):
917 return self.heap.PointerSize() * 2 1076 return self.heap.PointerSize() * 2
918 1077
919 def __init__(self, heap, map, address): 1078 def __init__(self, heap, map, address):
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1184
1026 def NameOffset(self): 1185 def NameOffset(self):
1027 return self.SourceOffset() + self.heap.PointerSize() 1186 return self.SourceOffset() + self.heap.PointerSize()
1028 1187
1029 def __init__(self, heap, map, address): 1188 def __init__(self, heap, map, address):
1030 HeapObject.__init__(self, heap, map, address) 1189 HeapObject.__init__(self, heap, map, address)
1031 self.source = self.ObjectField(self.SourceOffset()) 1190 self.source = self.ObjectField(self.SourceOffset())
1032 self.name = self.ObjectField(self.NameOffset()) 1191 self.name = self.ObjectField(self.NameOffset())
1033 1192
1034 1193
1194 class CodeCache(HeapObject):
1195 def DefaultCacheOffset(self):
1196 return self.heap.PointerSize()
1197
1198 def NormalTypeCacheOffset(self):
1199 return self.DefaultCacheOffset() + self.heap.PointerSize()
1200
1201 def __init__(self, heap, map, address):
1202 HeapObject.__init__(self, heap, map, address)
1203 self.default_cache = self.ObjectField(self.DefaultCacheOffset())
1204 self.normal_type_cache = self.ObjectField(self.NormalTypeCacheOffset())
1205
1206 def Print(self, p):
1207 p.Print("CodeCache(%s) {" % self.heap.reader.FormatIntPtr(self.address))
1208 p.Indent()
1209 p.Print("default cache: %s" % self.default_cache)
1210 p.Print("normal type cache: %s" % self.normal_type_cache)
1211 p.Dedent()
1212 p.Print("}")
1213
1214
1035 class Code(HeapObject): 1215 class Code(HeapObject):
1036 CODE_ALIGNMENT_MASK = (1 << 5) - 1 1216 CODE_ALIGNMENT_MASK = (1 << 5) - 1
1037 1217
1038 def InstructionSizeOffset(self): 1218 def InstructionSizeOffset(self):
1039 return self.heap.PointerSize() 1219 return self.heap.PointerSize()
1040 1220
1041 @staticmethod 1221 @staticmethod
1042 def HeaderSize(heap): 1222 def HeaderSize(heap):
1043 return (heap.PointerSize() + heap.IntSize() + \ 1223 return (heap.PointerSize() + heap.IntSize() + \
1044 4 * heap.PointerSize() + 3 * heap.IntSize() + \ 1224 4 * heap.PointerSize() + 3 * heap.IntSize() + \
(...skipping 30 matching lines...) Expand all
1075 "SHORT_EXTERNAL_SYMBOL_TYPE": ExternalString, 1255 "SHORT_EXTERNAL_SYMBOL_TYPE": ExternalString,
1076 "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString, 1256 "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
1077 "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString, 1257 "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
1078 "STRING_TYPE": SeqString, 1258 "STRING_TYPE": SeqString,
1079 "ASCII_STRING_TYPE": SeqString, 1259 "ASCII_STRING_TYPE": SeqString,
1080 "CONS_STRING_TYPE": ConsString, 1260 "CONS_STRING_TYPE": ConsString,
1081 "CONS_ASCII_STRING_TYPE": ConsString, 1261 "CONS_ASCII_STRING_TYPE": ConsString,
1082 "EXTERNAL_STRING_TYPE": ExternalString, 1262 "EXTERNAL_STRING_TYPE": ExternalString,
1083 "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE": ExternalString, 1263 "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE": ExternalString,
1084 "EXTERNAL_ASCII_STRING_TYPE": ExternalString, 1264 "EXTERNAL_ASCII_STRING_TYPE": ExternalString,
1085
1086 "MAP_TYPE": Map, 1265 "MAP_TYPE": Map,
1087 "ODDBALL_TYPE": Oddball, 1266 "ODDBALL_TYPE": Oddball,
1088 "FIXED_ARRAY_TYPE": FixedArray, 1267 "FIXED_ARRAY_TYPE": FixedArray,
1089 "JS_FUNCTION_TYPE": JSFunction, 1268 "JS_FUNCTION_TYPE": JSFunction,
1090 "SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo, 1269 "SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo,
1091 "SCRIPT_TYPE": Script, 1270 "SCRIPT_TYPE": Script,
1092 "CODE_TYPE": Code 1271 "CODE_CACHE_TYPE": CodeCache,
1272 "CODE_TYPE": Code,
1093 } 1273 }
1094 1274
1095 def __init__(self, reader, stack_map): 1275 def __init__(self, reader, stack_map):
1096 self.reader = reader 1276 self.reader = reader
1097 self.stack_map = stack_map 1277 self.stack_map = stack_map
1098 self.objects = {} 1278 self.objects = {}
1099 1279
1100 def FindObjectOrSmi(self, tagged_address): 1280 def FindObjectOrSmi(self, tagged_address):
1101 if (tagged_address & 1) == 0: return tagged_address / 2 1281 if (tagged_address & 1) == 0: return tagged_address / 2
1102 return self.FindObject(tagged_address) 1282 return self.FindObject(tagged_address)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 1320
1141 def ObjectAlignmentMask(self): 1321 def ObjectAlignmentMask(self):
1142 return self.PointerSize() - 1 1322 return self.PointerSize() - 1
1143 1323
1144 def MapAlignmentMask(self): 1324 def MapAlignmentMask(self):
1145 if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64: 1325 if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64:
1146 return (1 << 4) - 1 1326 return (1 << 4) - 1
1147 elif self.reader.arch == MD_CPU_ARCHITECTURE_X86: 1327 elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
1148 return (1 << 5) - 1 1328 return (1 << 5) - 1
1149 1329
1330 def PageAlignmentMask(self):
1331 return (1 << 20) - 1
1332
1333
1334 class KnownObject(HeapObject):
1335 def __init__(self, heap, known_name):
1336 HeapObject.__init__(self, heap, None, None)
1337 self.known_name = known_name
1338
1339 def __str__(self):
1340 return "<%s>" % self.known_name
1341
1342
1343 class KnownMap(HeapObject):
1344 def __init__(self, heap, known_name, instance_type):
1345 HeapObject.__init__(self, heap, None, None)
1346 self.instance_type = instance_type
1347 self.known_name = known_name
1348
1349 def __str__(self):
1350 return "<%s>" % self.known_name
1351
1352
1353 class InspectionPadawan(object):
1354 """The padawan can improve annotations by sensing well-known objects."""
1355 def __init__(self, reader, heap):
1356 self.reader = reader
1357 self.heap = heap
1358 self.known_first_map_page = 0
1359 self.known_first_data_page = 0
1360 self.known_first_pointer_page = 0
1361
1362 def __getattr__(self, name):
1363 """An InspectionPadawan can be used instead of V8Heap, even though
1364 it does not inherit from V8Heap (aka. mixin)."""
1365 return getattr(self.heap, name)
1366
1367 def GetPageOffset(self, tagged_address):
1368 return tagged_address & self.heap.PageAlignmentMask()
1369
1370 def IsInKnownMapSpace(self, tagged_address):
1371 page_address = tagged_address & ~self.heap.PageAlignmentMask()
1372 return page_address == self.known_first_map_page
1373
1374 def IsInKnownOldSpace(self, tagged_address):
1375 page_address = tagged_address & ~self.heap.PageAlignmentMask()
1376 return page_address in [self.known_first_data_page,
1377 self.known_first_pointer_page]
1378
1379 def ContainingKnownOldSpaceName(self, tagged_address):
1380 page_address = tagged_address & ~self.heap.PageAlignmentMask()
1381 if page_address == self.known_first_data_page: return "OLD_DATA_SPACE"
1382 if page_address == self.known_first_pointer_page: return "OLD_POINTER_SPACE"
1383 return None
1384
1385 def SenseObject(self, tagged_address):
1386 if self.IsInKnownOldSpace(tagged_address):
1387 offset = self.GetPageOffset(tagged_address)
1388 lookup_key = (self.ContainingKnownOldSpaceName(tagged_address), offset)
1389 known_obj_name = KNOWN_OBJECTS.get(lookup_key)
1390 if known_obj_name:
1391 return KnownObject(self, known_obj_name)
1392 if self.IsInKnownMapSpace(tagged_address):
1393 known_map = self.SenseMap(tagged_address)
1394 if known_map:
1395 return known_map
1396 found_obj = self.heap.FindObject(tagged_address)
1397 if found_obj: return found_ob
1398 address = tagged_address - 1
1399 if self.reader.IsValidAddress(address):
1400 map_tagged_address = self.reader.ReadUIntPtr(address)
1401 map = self.SenseMap(map_tagged_address)
1402 if map is None: return None
1403 instance_type_name = INSTANCE_TYPES.get(map.instance_type)
1404 if instance_type_name is None: return None
1405 cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
1406 return cls(self, map, address)
1407 return None
1408
1409 def SenseMap(self, tagged_address):
1410 if self.IsInKnownMapSpace(tagged_address):
1411 offset = self.GetPageOffset(tagged_address)
1412 known_map_info = KNOWN_MAPS.get(offset)
1413 if known_map_info:
1414 known_map_type, known_map_name = known_map_info
1415 return KnownMap(self, known_map_name, known_map_type)
1416 found_map = self.heap.FindMap(tagged_address)
1417 if found_map: return found_map
1418 return None
1419
1420 def FindObjectOrSmi(self, tagged_address):
1421 """When used as a mixin in place of V8Heap."""
1422 found_obj = self.SenseObject(tagged_address)
1423 if found_obj: return found_obj
1424 if (tagged_address & 1) == 0:
1425 return "Smi(%d)" % (tagged_address / 2)
1426 else:
1427 return "Unknown(%s)" % self.reader.FormatIntPtr(tagged_address)
1428
1429 def FindObject(self, tagged_address):
1430 """When used as a mixin in place of V8Heap."""
1431 raise NotImplementedError
1432
1433 def FindMap(self, tagged_address):
1434 """When used as a mixin in place of V8Heap."""
1435 raise NotImplementedError
1436
1437 def PrintKnowledge(self):
1438 print " known_first_map_page = %s\n"\
1439 " known_first_data_page = %s\n"\
1440 " known_first_pointer_page = %s" % (
1441 self.reader.FormatIntPtr(self.known_first_map_page),
1442 self.reader.FormatIntPtr(self.known_first_data_page),
1443 self.reader.FormatIntPtr(self.known_first_pointer_page))
1444
1445
1446 class InspectionShell(cmd.Cmd):
1447 def __init__(self, reader, heap):
1448 cmd.Cmd.__init__(self)
1449 self.reader = reader
1450 self.heap = heap
1451 self.padawan = InspectionPadawan(reader, heap)
1452 self.prompt = "(grok) "
1453
1454 def do_dd(self, address):
1455 """
1456 Interpret memory at the given address (if available) as a sequence
1457 of words. Automatic alignment is not performed.
1458 """
1459 start = int(address, 16)
1460 if (start & self.heap.ObjectAlignmentMask()) != 0:
1461 print "Warning: Dumping un-aligned memory, is this what you had in mind?"
1462 for slot in xrange(start,
1463 start + self.reader.PointerSize() * 10,
1464 self.reader.PointerSize()):
1465 maybe_address = self.reader.ReadUIntPtr(slot)
1466 heap_object = self.padawan.SenseObject(maybe_address)
1467 print "%s: %s %s" % (self.reader.FormatIntPtr(slot),
1468 self.reader.FormatIntPtr(maybe_address),
1469 heap_object or '')
1470
1471 def do_do(self, address):
1472 """
1473 Interpret memory at the given address as a V8 object. Automatic
1474 alignment makes sure that you can pass tagged as well as un-tagged
1475 addresses.
1476 """
1477 address = int(address, 16)
1478 if (address & self.heap.ObjectAlignmentMask()) == 0:
1479 address = address + 1
1480 elif (address & self.heap.ObjectAlignmentMask()) != 1:
1481 print "Address doesn't look like a valid pointer!"
1482 return
1483 heap_object = self.padawan.SenseObject(address)
1484 if heap_object:
1485 heap_object.Print(Printer())
1486 else:
1487 print "Address cannot be interpreted as object!"
1488
1489 def do_dp(self, address):
1490 """
1491 Interpret memory at the given address as being on a V8 heap page
1492 and print information about the page header (if available).
1493 """
1494 address = int(address, 16)
1495 page_address = address & ~self.heap.PageAlignmentMask()
1496 if self.reader.IsValidAddress(page_address):
1497 raise NotImplementedError
1498 else:
1499 print "Page header is not available!"
1500
1501 def do_k(self, arguments):
1502 """
1503 Teach V8 heap layout information to the inspector. This increases
1504 the amount of annotations the inspector can produce while dumping
1505 data. The first page of each heap space is of particular interest
1506 because it contains known objects that do not move.
1507 """
1508 self.padawan.PrintKnowledge()
1509
1510 def do_km(self, address):
1511 """
1512 Teach V8 heap layout information to the inspector. Set the first
1513 map-space page by passing any pointer into that page.
1514 """
1515 address = int(address, 16)
1516 page_address = address & ~self.heap.PageAlignmentMask()
1517 self.padawan.known_first_map_page = page_address
1518
1519 def do_kd(self, address):
1520 """
1521 Teach V8 heap layout information to the inspector. Set the first
1522 data-space page by passing any pointer into that page.
1523 """
1524 address = int(address, 16)
1525 page_address = address & ~self.heap.PageAlignmentMask()
1526 self.padawan.known_first_data_page = page_address
1527
1528 def do_kp(self, address):
1529 """
1530 Teach V8 heap layout information to the inspector. Set the first
1531 pointer-space page by passing any pointer into that page.
1532 """
1533 address = int(address, 16)
1534 page_address = address & ~self.heap.PageAlignmentMask()
1535 self.padawan.known_first_pointer_page = page_address
1536
1537 def do_s(self, word):
1538 """
1539 Search for a given word in available memory regions. The given word
1540 is expanded to full pointer size and searched at aligned as well as
1541 un-aligned memory locations. Use 'sa' to search aligned locations
1542 only.
1543 """
1544 try:
1545 word = int(word, 0)
1546 except ValueError:
1547 print "Malformed word, prefix with '0x' to use hexadecimal format."
1548 return
1549 print "Searching for word %d/0x%s:" % (word, self.reader.FormatIntPtr(word))
1550 self.reader.FindWord(word)
1551
1552 def do_sh(self, none):
1553 """
1554 Search for the V8 Heap object in all available memory regions. You
1555 might get lucky and find this rare treasure full of invaluable
1556 information.
1557 """
1558 raise NotImplementedError
1559
1560 def do_list(self, smth):
1561 """
1562 List all available memory regions.
1563 """
1564 def print_region(reader, start, size, location):
1565 print " %s - %s (%d bytes)" % (reader.FormatIntPtr(start),
1566 reader.FormatIntPtr(start + size),
1567 size)
1568 print "Available memory regions:"
1569 self.reader.ForEachMemoryRegion(print_region)
1570
1150 1571
1151 EIP_PROXIMITY = 64 1572 EIP_PROXIMITY = 64
1152 1573
1153 CONTEXT_FOR_ARCH = { 1574 CONTEXT_FOR_ARCH = {
1154 MD_CPU_ARCHITECTURE_AMD64: 1575 MD_CPU_ARCHITECTURE_AMD64:
1155 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'], 1576 ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'],
1156 MD_CPU_ARCHITECTURE_X86: 1577 MD_CPU_ARCHITECTURE_X86:
1157 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip'] 1578 ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
1158 } 1579 }
1159 1580
1160 class InspectionShell(cmd.Cmd):
1161 def __init__(self, reader, heap):
1162 cmd.Cmd.__init__(self)
1163 self.reader = reader
1164 self.heap = heap
1165 self.prompt = "(grok) "
1166
1167 def do_dd(self, address):
1168 "Interpret memory at the given address (if available)"\
1169 " as a sequence of words."
1170 start = int(address, 16)
1171 for slot in xrange(start,
1172 start + self.reader.PointerSize() * 10,
1173 self.reader.PointerSize()):
1174 maybe_address = self.reader.ReadUIntPtr(slot)
1175 heap_object = self.heap.FindObject(maybe_address)
1176 print "%s: %s" % (self.reader.FormatIntPtr(slot),
1177 self.reader.FormatIntPtr(maybe_address))
1178 if heap_object:
1179 heap_object.Print(Printer())
1180 print
1181
1182 def do_s(self, word):
1183 "Search for a given word in available memory regions"
1184 word = int(word, 0)
1185 print "searching for word", word
1186 self.reader.FindWord(word)
1187
1188 def do_list(self, smth):
1189 """List all available memory regions."""
1190 def print_region(reader, start, size, location):
1191 print "%s - %s" % (reader.FormatIntPtr(start),
1192 reader.FormatIntPtr(start + size))
1193
1194 self.reader.ForEachMemoryRegion(print_region)
1195 1581
1196 def AnalyzeMinidump(options, minidump_name): 1582 def AnalyzeMinidump(options, minidump_name):
1197 reader = MinidumpReader(options, minidump_name) 1583 reader = MinidumpReader(options, minidump_name)
1198 heap = None 1584 heap = None
1199 DebugPrint("========================================") 1585 DebugPrint("========================================")
1200 if reader.exception is None: 1586 if reader.exception is None:
1201 print "Minidump has no exception info" 1587 print "Minidump has no exception info"
1202 else: 1588 else:
1203 print "Exception info:" 1589 print "Exception info:"
1204 exception_thread = reader.thread_map[reader.exception.thread_id] 1590 exception_thread = reader.thread_map[reader.exception.thread_id]
(...skipping 28 matching lines...) Expand all
1233 lines = reader.GetDisasmLines(disasm_start, disasm_bytes) 1619 lines = reader.GetDisasmLines(disasm_start, disasm_bytes)
1234 1620
1235 for line in lines: 1621 for line in lines:
1236 print FormatDisasmLine(disasm_start, heap, line) 1622 print FormatDisasmLine(disasm_start, heap, line)
1237 print 1623 print
1238 1624
1239 if heap is None: 1625 if heap is None:
1240 heap = V8Heap(reader, None) 1626 heap = V8Heap(reader, None)
1241 1627
1242 if options.full: 1628 if options.full:
1243 do_dump(reader, heap) 1629 FullDump(reader, heap)
1244 1630
1245 if options.shell: 1631 if options.shell:
1246 InspectionShell(reader, heap).cmdloop("type help to get help") 1632 InspectionShell(reader, heap).cmdloop("type help to get help")
1247 else: 1633 else:
1248 if reader.exception is not None: 1634 if reader.exception is not None:
1249 print "Annotated stack (from exception.esp to bottom):" 1635 print "Annotated stack (from exception.esp to bottom):"
1250 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): 1636 for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
1251 maybe_address = reader.ReadUIntPtr(slot) 1637 maybe_address = reader.ReadUIntPtr(slot)
1252 heap_object = heap.FindObject(maybe_address) 1638 heap_object = heap.FindObject(maybe_address)
1253 print "%s: %s" % (reader.FormatIntPtr(slot), 1639 print "%s: %s" % (reader.FormatIntPtr(slot),
1254 reader.FormatIntPtr(maybe_address)) 1640 reader.FormatIntPtr(maybe_address))
1255 if heap_object: 1641 if heap_object:
1256 heap_object.Print(Printer()) 1642 heap_object.Print(Printer())
1257 print 1643 print
1258 1644
1259 reader.Dispose() 1645 reader.Dispose()
1260 1646
1261 1647
1262 if __name__ == "__main__": 1648 if __name__ == "__main__":
1263 parser = optparse.OptionParser(USAGE) 1649 parser = optparse.OptionParser(USAGE)
1264 parser.add_option("-s", "--shell", dest="shell", action="store_true") 1650 parser.add_option("-s", "--shell", dest="shell", action="store_true",
1265 parser.add_option("-f", "--full", dest="full", action="store_true") 1651 help="start an interactive inspector shell")
1652 parser.add_option("-f", "--full", dest="full", action="store_true",
1653 help="dump all information contained in the minidump")
1266 options, args = parser.parse_args() 1654 options, args = parser.parse_args()
1267 if len(args) != 1: 1655 if len(args) != 1:
1268 parser.print_help() 1656 parser.print_help()
1269 sys.exit(1) 1657 sys.exit(1)
1270 AnalyzeMinidump(options, args[0]) 1658 AnalyzeMinidump(options, args[0])
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698