Revision: 11684
Author: [email protected]
Date: Thu May 31 01:01:54 2012
Log: Implement grokdump annotations for well-known objects.
[email protected]
TEST=tools/grokdump.py
Review URL: https://chromiumcodereview.appspot.com/10441088
http://code.google.com/p/v8/source/detail?r=11684
Modified:
/branches/bleeding_edge/tools/grokdump.py
=======================================
--- /branches/bleeding_edge/tools/grokdump.py Tue May 22 04:08:05 2012
+++ /branches/bleeding_edge/tools/grokdump.py Thu May 31 01:01:54 2012
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2011 the V8 project authors. All rights reserved.
+# Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
@@ -40,19 +40,17 @@
import struct
-USAGE="""usage: %prog [OPTION]...
+USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
Minidump analyzer.
Shows the processor state at the point of exception including the
stack of the active thread and the referenced objects in the V8
heap. Code objects are disassembled and the addresses linked from the
-stack (pushed return addresses) are marked with "=>".
-
+stack (e.g. pushed return addresses) are marked with "=>".
Examples:
- $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp
-"""
+ $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp"""
DEBUG=False
@@ -108,7 +106,7 @@
return Raw
-def do_dump(reader, heap):
+def FullDump(reader, heap):
"""Dump all available memory regions."""
def dump_region(reader, start, size, location):
print
@@ -420,7 +418,7 @@
self.minidump = mmap.mmap(self.minidump_file.fileno(), 0,
mmap.MAP_PRIVATE)
self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
if self.header.signature != MinidumpReader._HEADER_MAGIC:
- print >>sys.stderr, "Warning: unsupported minidump header magic"
+ print >>sys.stderr, "Warning: Unsupported minidump header magic!"
DebugPrint(self.header)
directories = []
offset = self.header.stream_directories_rva
@@ -464,7 +462,7 @@
DebugPrint(thread)
self.thread_map[thread.id] = thread
elif d.stream_type == MD_MEMORY_LIST_STREAM:
- print >>sys.stderr, "Warning: not a full minidump"
+ print >>sys.stderr, "Warning: This is not a full minidump!"
assert self.memory_list is None
self.memory_list = MINIDUMP_MEMORY_LIST.Read(
self.minidump, d.location.rva)
@@ -577,14 +575,14 @@
for r in self.memory_list.ranges:
cb(self, r.start, r.memory.data_size, r.memory.rva)
- def FindWord(self, word):
+ def FindWord(self, word, alignment=0):
def search_inside_region(reader, start, size, location):
- for loc in xrange(location, location + size):
+ location = (location + alignment) & ~alignment
+ for loc in xrange(location, location + size - self.PointerSize()):
if reader._ReadWord(loc) == word:
slot = start + (loc - location)
print "%s: %s" % (reader.FormatIntPtr(slot),
reader.FormatIntPtr(word))
-
self.ForEachMemoryRegion(search_inside_region)
def FindLocation(self, address):
@@ -710,24 +708,182 @@
156: "SCRIPT_TYPE",
157: "CODE_CACHE_TYPE",
158: "POLYMORPHIC_CODE_CACHE_TYPE",
- 161: "FIXED_ARRAY_TYPE",
+ 159: "TYPE_FEEDBACK_INFO_TYPE",
+ 160: "ALIASED_ARGUMENTS_ENTRY_TYPE",
+ 163: "FIXED_ARRAY_TYPE",
145: "FIXED_DOUBLE_ARRAY_TYPE",
- 162: "SHARED_FUNCTION_INFO_TYPE",
- 163: "JS_MESSAGE_OBJECT_TYPE",
- 166: "JS_VALUE_TYPE",
- 167: "JS_OBJECT_TYPE",
- 168: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
- 169: "JS_GLOBAL_OBJECT_TYPE",
- 170: "JS_BUILTINS_OBJECT_TYPE",
- 171: "JS_GLOBAL_PROXY_TYPE",
- 172: "JS_ARRAY_TYPE",
- 165: "JS_PROXY_TYPE",
- 175: "JS_WEAK_MAP_TYPE",
- 176: "JS_REGEXP_TYPE",
- 177: "JS_FUNCTION_TYPE",
- 164: "JS_FUNCTION_PROXY_TYPE",
- 159: "DEBUG_INFO_TYPE",
- 160: "BREAK_POINT_INFO_TYPE",
+ 164: "SHARED_FUNCTION_INFO_TYPE",
+ 165: "JS_MESSAGE_OBJECT_TYPE",
+ 168: "JS_VALUE_TYPE",
+ 169: "JS_DATE_TYPE",
+ 170: "JS_OBJECT_TYPE",
+ 171: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+ 172: "JS_MODULE_TYPE",
+ 173: "JS_GLOBAL_OBJECT_TYPE",
+ 174: "JS_BUILTINS_OBJECT_TYPE",
+ 175: "JS_GLOBAL_PROXY_TYPE",
+ 176: "JS_ARRAY_TYPE",
+ 167: "JS_PROXY_TYPE",
+ 179: "JS_WEAK_MAP_TYPE",
+ 180: "JS_REGEXP_TYPE",
+ 181: "JS_FUNCTION_TYPE",
+ 166: "JS_FUNCTION_PROXY_TYPE",
+ 161: "DEBUG_INFO_TYPE",
+ 162: "BREAK_POINT_INFO_TYPE",
+}
+
+
+# List of known V8 maps. Used to determine the instance type and name
+# for maps that are part of the root-set and hence on the first page of
+# the map-space. Obtained by adding the code below to an IA32 release
+# build with enabled snapshots to the end of the Isolate::Init method.
+#
+# #define ROOT_LIST_CASE(type, name, camel_name) \
+# if (o == heap_.name()) n = #camel_name;
+# #define STRUCT_LIST_CASE(upper_name, camel_name, name) \
+# if (o == heap_.name##_map()) n = #camel_name "Map";
+# HeapObjectIterator it(heap_.map_space());
+# printf("KNOWN_MAPS = {\n");
+# for (Object* o = it.Next(); o != NULL; o = it.Next()) {
+# Map* m = Map::cast(o);
+# const char* n = "";
+# intptr_t p = reinterpret_cast<intptr_t>(m) & 0xfffff;
+# int t = m->instance_type();
+# ROOT_LIST(ROOT_LIST_CASE)
+# STRUCT_LIST(STRUCT_LIST_CASE)
+# printf(" 0x%05x: (%d, \"%s\"),\n", p, t, n);
+# }
+# printf("}\n");
+KNOWN_MAPS = {
+ 0x08081: (134, "ByteArrayMap"),
+ 0x080a1: (128, "MetaMap"),
+ 0x080c1: (130, "OddballMap"),
+ 0x080e1: (163, "FixedArrayMap"),
+ 0x08101: (68, "AsciiSymbolMap"),
+ 0x08121: (132, "HeapNumberMap"),
+ 0x08141: (135, "FreeSpaceMap"),
+ 0x08161: (146, "OnePointerFillerMap"),
+ 0x08181: (146, "TwoPointerFillerMap"),
+ 0x081a1: (131, "GlobalPropertyCellMap"),
+ 0x081c1: (164, "SharedFunctionInfoMap"),
+ 0x081e1: (4, "AsciiStringMap"),
+ 0x08201: (163, "GlobalContextMap"),
+ 0x08221: (129, "CodeMap"),
+ 0x08241: (163, "ScopeInfoMap"),
+ 0x08261: (163, "FixedCOWArrayMap"),
+ 0x08281: (145, "FixedDoubleArrayMap"),
+ 0x082a1: (163, "HashTableMap"),
+ 0x082c1: (0, "StringMap"),
+ 0x082e1: (64, "SymbolMap"),
+ 0x08301: (1, "ConsStringMap"),
+ 0x08321: (5, "ConsAsciiStringMap"),
+ 0x08341: (3, "SlicedStringMap"),
+ 0x08361: (7, "SlicedAsciiStringMap"),
+ 0x08381: (65, "ConsSymbolMap"),
+ 0x083a1: (69, "ConsAsciiSymbolMap"),
+ 0x083c1: (66, "ExternalSymbolMap"),
+ 0x083e1: (74, "ExternalSymbolWithAsciiDataMap"),
+ 0x08401: (70, "ExternalAsciiSymbolMap"),
+ 0x08421: (2, "ExternalStringMap"),
+ 0x08441: (10, "ExternalStringWithAsciiDataMap"),
+ 0x08461: (6, "ExternalAsciiStringMap"),
+ 0x08481: (82, "ShortExternalSymbolMap"),
+ 0x084a1: (90, "ShortExternalSymbolWithAsciiDataMap"),
+ 0x084c1: (86, "ShortExternalAsciiSymbolMap"),
+ 0x084e1: (18, "ShortExternalStringMap"),
+ 0x08501: (26, "ShortExternalStringWithAsciiDataMap"),
+ 0x08521: (22, "ShortExternalAsciiStringMap"),
+ 0x08541: (0, "UndetectableStringMap"),
+ 0x08561: (4, "UndetectableAsciiStringMap"),
+ 0x08581: (144, "ExternalPixelArrayMap"),
+ 0x085a1: (136, "ExternalByteArrayMap"),
+ 0x085c1: (137, "ExternalUnsignedByteArrayMap"),
+ 0x085e1: (138, "ExternalShortArrayMap"),
+ 0x08601: (139, "ExternalUnsignedShortArrayMap"),
+ 0x08621: (140, "ExternalIntArrayMap"),
+ 0x08641: (141, "ExternalUnsignedIntArrayMap"),
+ 0x08661: (142, "ExternalFloatArrayMap"),
+ 0x08681: (143, "ExternalDoubleArrayMap"),
+ 0x086a1: (163, "NonStrictArgumentsElementsMap"),
+ 0x086c1: (163, "FunctionContextMap"),
+ 0x086e1: (163, "CatchContextMap"),
+ 0x08701: (163, "WithContextMap"),
+ 0x08721: (163, "BlockContextMap"),
+ 0x08741: (163, "ModuleContextMap"),
+ 0x08761: (165, "JSMessageObjectMap"),
+ 0x08781: (133, "ForeignMap"),
+ 0x087a1: (170, "NeanderMap"),
+ 0x087c1: (158, "PolymorphicCodeCacheMap"),
+ 0x087e1: (156, "ScriptMap"),
+ 0x08801: (147, "AccessorInfoMap"),
+ 0x08821: (148, "AccessorPairMap"),
+ 0x08841: (149, "AccessCheckInfoMap"),
+ 0x08861: (150, "InterceptorInfoMap"),
+ 0x08881: (151, "CallHandlerInfoMap"),
+ 0x088a1: (152, "FunctionTemplateInfoMap"),
+ 0x088c1: (153, "ObjectTemplateInfoMap"),
+ 0x088e1: (154, "SignatureInfoMap"),
+ 0x08901: (155, "TypeSwitchInfoMap"),
+ 0x08921: (157, "CodeCacheMap"),
+ 0x08941: (159, "TypeFeedbackInfoMap"),
+ 0x08961: (160, "AliasedArgumentsEntryMap"),
+ 0x08981: (161, "DebugInfoMap"),
+ 0x089a1: (162, "BreakPointInfoMap"),
+}
+
+
+# List of known V8 objects. Used to determine name for objects that are
+# part of the root-set and hence on the first page of various old-space
+# paged. Obtained by adding the code below to an IA32 release build with
+# enabled snapshots to the end of the Isolate::Init method.
+#
+# #define ROOT_LIST_CASE(type, name, camel_name) \
+# if (o == heap_.name()) n = #camel_name;
+# OldSpaces spit;
+# printf("KNOWN_OBJECTS = {\n");
+# for (PagedSpace* s = spit.next(); s != NULL; s = spit.next()) {
+# HeapObjectIterator it(s);
+# const char* sname = AllocationSpaceName(s->identity());
+# for (Object* o = it.Next(); o != NULL; o = it.Next()) {
+# const char* n = NULL;
+# intptr_t p = reinterpret_cast<intptr_t>(o) & 0xfffff;
+# ROOT_LIST(ROOT_LIST_CASE)
+# if (n != NULL) {
+# printf(" (\"%s\", 0x%05x): \"%s\",\n", sname, p, n);
+# }
+# }
+# }
+# printf("}\n");
+KNOWN_OBJECTS = {
+ ("OLD_POINTER_SPACE", 0x08081): "NullValue",
+ ("OLD_POINTER_SPACE", 0x08091): "UndefinedValue",
+ ("OLD_POINTER_SPACE", 0x080a1): "InstanceofCacheMap",
+ ("OLD_POINTER_SPACE", 0x080b1): "TrueValue",
+ ("OLD_POINTER_SPACE", 0x080c1): "FalseValue",
+ ("OLD_POINTER_SPACE", 0x080d1): "NoInterceptorResultSentinel",
+ ("OLD_POINTER_SPACE", 0x080e1): "ArgumentsMarker",
+ ("OLD_POINTER_SPACE", 0x080f1): "NumberStringCache",
+ ("OLD_POINTER_SPACE", 0x088f9): "SingleCharacterStringCache",
+ ("OLD_POINTER_SPACE", 0x08b01): "StringSplitCache",
+ ("OLD_POINTER_SPACE", 0x08f09): "TerminationException",
+ ("OLD_POINTER_SPACE", 0x08f19): "MessageListeners",
+ ("OLD_POINTER_SPACE", 0x08f35): "CodeStubs",
+ ("OLD_POINTER_SPACE", 0x09b61): "NonMonomorphicCache",
+ ("OLD_POINTER_SPACE", 0x0a175): "PolymorphicCodeCache",
+ ("OLD_POINTER_SPACE", 0x0a17d): "NativesSourceCache",
+ ("OLD_POINTER_SPACE", 0x0a1bd): "EmptyScript",
+ ("OLD_POINTER_SPACE", 0x0a1f9): "IntrinsicFunctionNames",
+ ("OLD_POINTER_SPACE", 0x24a49): "SymbolTable",
+ ("OLD_DATA_SPACE", 0x08081): "EmptyFixedArray",
+ ("OLD_DATA_SPACE", 0x080a1): "NanValue",
+ ("OLD_DATA_SPACE", 0x0811d): "EmptyByteArray",
+ ("OLD_DATA_SPACE", 0x08125): "EmptyString",
+ ("OLD_DATA_SPACE", 0x08131): "EmptyDescriptorArray",
+ ("OLD_DATA_SPACE", 0x08259): "InfinityValue",
+ ("OLD_DATA_SPACE", 0x08265): "MinusZeroValue",
+ ("OLD_DATA_SPACE", 0x08271): "PrototypeAccessors",
+ ("CODE_SPACE", 0x12b81): "JsEntryCode",
+ ("CODE_SPACE", 0x12c61): "JsConstructEntryCode",
}
@@ -906,7 +1062,10 @@
p.Print(str(self))
def __str__(self):
- return "<%s>" % self.to_string.GetChars()
+ if self.to_string:
+ return "Oddball(%08x, <%s>)" % (self.address,
self.to_string.GetChars())
+ else:
+ return "Oddball(%08x, kind=%s)" % (self.address, "???")
class FixedArray(HeapObject):
@@ -1032,6 +1191,27 @@
self.name = self.ObjectField(self.NameOffset())
+class CodeCache(HeapObject):
+ def DefaultCacheOffset(self):
+ return self.heap.PointerSize()
+
+ def NormalTypeCacheOffset(self):
+ return self.DefaultCacheOffset() + self.heap.PointerSize()
+
+ def __init__(self, heap, map, address):
+ HeapObject.__init__(self, heap, map, address)
+ self.default_cache = self.ObjectField(self.DefaultCacheOffset())
+ self.normal_type_cache = self.ObjectField(self.NormalTypeCacheOffset())
+
+ def Print(self, p):
+ p.Print("CodeCache(%s) {" %
self.heap.reader.FormatIntPtr(self.address))
+ p.Indent()
+ p.Print("default cache: %s" % self.default_cache)
+ p.Print("normal type cache: %s" % self.normal_type_cache)
+ p.Dedent()
+ p.Print("}")
+
+
class Code(HeapObject):
CODE_ALIGNMENT_MASK = (1 << 5) - 1
@@ -1082,14 +1262,14 @@
"EXTERNAL_STRING_TYPE": ExternalString,
"EXTERNAL_STRING_WITH_ASCII_DATA_TYPE": ExternalString,
"EXTERNAL_ASCII_STRING_TYPE": ExternalString,
-
"MAP_TYPE": Map,
"ODDBALL_TYPE": Oddball,
"FIXED_ARRAY_TYPE": FixedArray,
"JS_FUNCTION_TYPE": JSFunction,
"SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo,
"SCRIPT_TYPE": Script,
- "CODE_TYPE": Code
+ "CODE_CACHE_TYPE": CodeCache,
+ "CODE_TYPE": Code,
}
def __init__(self, reader, stack_map):
@@ -1147,52 +1327,258 @@
elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
return (1 << 5) - 1
-
-EIP_PROXIMITY = 64
-
-CONTEXT_FOR_ARCH = {
- MD_CPU_ARCHITECTURE_AMD64:
- ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'],
- MD_CPU_ARCHITECTURE_X86:
- ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
-}
+ def PageAlignmentMask(self):
+ return (1 << 20) - 1
+
+
+class KnownObject(HeapObject):
+ def __init__(self, heap, known_name):
+ HeapObject.__init__(self, heap, None, None)
+ self.known_name = known_name
+
+ def __str__(self):
+ return "<%s>" % self.known_name
+
+
+class KnownMap(HeapObject):
+ def __init__(self, heap, known_name, instance_type):
+ HeapObject.__init__(self, heap, None, None)
+ self.instance_type = instance_type
+ self.known_name = known_name
+
+ def __str__(self):
+ return "<%s>" % self.known_name
+
+
+class InspectionPadawan(object):
+ """The padawan can improve annotations by sensing well-known objects."""
+ def __init__(self, reader, heap):
+ self.reader = reader
+ self.heap = heap
+ self.known_first_map_page = 0
+ self.known_first_data_page = 0
+ self.known_first_pointer_page = 0
+
+ def __getattr__(self, name):
+ """An InspectionPadawan can be used instead of V8Heap, even though
+ it does not inherit from V8Heap (aka. mixin)."""
+ return getattr(self.heap, name)
+
+ def GetPageOffset(self, tagged_address):
+ return tagged_address & self.heap.PageAlignmentMask()
+
+ def IsInKnownMapSpace(self, tagged_address):
+ page_address = tagged_address & ~self.heap.PageAlignmentMask()
+ return page_address == self.known_first_map_page
+
+ def IsInKnownOldSpace(self, tagged_address):
+ page_address = tagged_address & ~self.heap.PageAlignmentMask()
+ return page_address in [self.known_first_data_page,
+ self.known_first_pointer_page]
+
+ def ContainingKnownOldSpaceName(self, tagged_address):
+ page_address = tagged_address & ~self.heap.PageAlignmentMask()
+ if page_address == self.known_first_data_page: return "OLD_DATA_SPACE"
+ if page_address == self.known_first_pointer_page:
return "OLD_POINTER_SPACE"
+ return None
+
+ def SenseObject(self, tagged_address):
+ if self.IsInKnownOldSpace(tagged_address):
+ offset = self.GetPageOffset(tagged_address)
+ lookup_key = (self.ContainingKnownOldSpaceName(tagged_address),
offset)
+ known_obj_name = KNOWN_OBJECTS.get(lookup_key)
+ if known_obj_name:
+ return KnownObject(self, known_obj_name)
+ if self.IsInKnownMapSpace(tagged_address):
+ known_map = self.SenseMap(tagged_address)
+ if known_map:
+ return known_map
+ found_obj = self.heap.FindObject(tagged_address)
+ if found_obj: return found_ob
+ address = tagged_address - 1
+ if self.reader.IsValidAddress(address):
+ map_tagged_address = self.reader.ReadUIntPtr(address)
+ map = self.SenseMap(map_tagged_address)
+ if map is None: return None
+ instance_type_name = INSTANCE_TYPES.get(map.instance_type)
+ if instance_type_name is None: return None
+ cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
+ return cls(self, map, address)
+ return None
+
+ def SenseMap(self, tagged_address):
+ if self.IsInKnownMapSpace(tagged_address):
+ offset = self.GetPageOffset(tagged_address)
+ known_map_info = KNOWN_MAPS.get(offset)
+ if known_map_info:
+ known_map_type, known_map_name = known_map_info
+ return KnownMap(self, known_map_name, known_map_type)
+ found_map = self.heap.FindMap(tagged_address)
+ if found_map: return found_map
+ return None
+
+ def FindObjectOrSmi(self, tagged_address):
+ """When used as a mixin in place of V8Heap."""
+ found_obj = self.SenseObject(tagged_address)
+ if found_obj: return found_obj
+ if (tagged_address & 1) == 0:
+ return "Smi(%d)" % (tagged_address / 2)
+ else:
+ return "Unknown(%s)" % self.reader.FormatIntPtr(tagged_address)
+
+ def FindObject(self, tagged_address):
+ """When used as a mixin in place of V8Heap."""
+ raise NotImplementedError
+
+ def FindMap(self, tagged_address):
+ """When used as a mixin in place of V8Heap."""
+ raise NotImplementedError
+
+ def PrintKnowledge(self):
+ print " known_first_map_page = %s\n"\
+ " known_first_data_page = %s\n"\
+ " known_first_pointer_page = %s" % (
+ self.reader.FormatIntPtr(self.known_first_map_page),
+ self.reader.FormatIntPtr(self.known_first_data_page),
+ self.reader.FormatIntPtr(self.known_first_pointer_page))
+
class InspectionShell(cmd.Cmd):
def __init__(self, reader, heap):
cmd.Cmd.__init__(self)
self.reader = reader
self.heap = heap
+ self.padawan = InspectionPadawan(reader, heap)
self.prompt = "(grok) "
def do_dd(self, address):
- "Interpret memory at the given address (if available)"\
- " as a sequence of words."
+ """
+ Interpret memory at the given address (if available) as a sequence
+ of words. Automatic alignment is not performed.
+ """
start = int(address, 16)
+ if (start & self.heap.ObjectAlignmentMask()) != 0:
+ print "Warning: Dumping un-aligned memory, is this what you had in
mind?"
for slot in xrange(start,
start + self.reader.PointerSize() * 10,
self.reader.PointerSize()):
maybe_address = self.reader.ReadUIntPtr(slot)
- heap_object = self.heap.FindObject(maybe_address)
- print "%s: %s" % (self.reader.FormatIntPtr(slot),
- self.reader.FormatIntPtr(maybe_address))
- if heap_object:
- heap_object.Print(Printer())
- print
+ heap_object = self.padawan.SenseObject(maybe_address)
+ print "%s: %s %s" % (self.reader.FormatIntPtr(slot),
+ self.reader.FormatIntPtr(maybe_address),
+ heap_object or '')
+
+ def do_do(self, address):
+ """
+ Interpret memory at the given address as a V8 object. Automatic
+ alignment makes sure that you can pass tagged as well as un-tagged
+ addresses.
+ """
+ address = int(address, 16)
+ if (address & self.heap.ObjectAlignmentMask()) == 0:
+ address = address + 1
+ elif (address & self.heap.ObjectAlignmentMask()) != 1:
+ print "Address doesn't look like a valid pointer!"
+ return
+ heap_object = self.padawan.SenseObject(address)
+ if heap_object:
+ heap_object.Print(Printer())
+ else:
+ print "Address cannot be interpreted as object!"
+
+ def do_dp(self, address):
+ """
+ Interpret memory at the given address as being on a V8 heap page
+ and print information about the page header (if available).
+ """
+ address = int(address, 16)
+ page_address = address & ~self.heap.PageAlignmentMask()
+ if self.reader.IsValidAddress(page_address):
+ raise NotImplementedError
+ else:
+ print "Page header is not available!"
+
+ def do_k(self, arguments):
+ """
+ Teach V8 heap layout information to the inspector. This increases
+ the amount of annotations the inspector can produce while dumping
+ data. The first page of each heap space is of particular interest
+ because it contains known objects that do not move.
+ """
+ self.padawan.PrintKnowledge()
+
+ def do_km(self, address):
+ """
+ Teach V8 heap layout information to the inspector. Set the first
+ map-space page by passing any pointer into that page.
+ """
+ address = int(address, 16)
+ page_address = address & ~self.heap.PageAlignmentMask()
+ self.padawan.known_first_map_page = page_address
+
+ def do_kd(self, address):
+ """
+ Teach V8 heap layout information to the inspector. Set the first
+ data-space page by passing any pointer into that page.
+ """
+ address = int(address, 16)
+ page_address = address & ~self.heap.PageAlignmentMask()
+ self.padawan.known_first_data_page = page_address
+
+ def do_kp(self, address):
+ """
+ Teach V8 heap layout information to the inspector. Set the first
+ pointer-space page by passing any pointer into that page.
+ """
+ address = int(address, 16)
+ page_address = address & ~self.heap.PageAlignmentMask()
+ self.padawan.known_first_pointer_page = page_address
def do_s(self, word):
- "Search for a given word in available memory regions"
- word = int(word, 0)
- print "searching for word", word
+ """
+ Search for a given word in available memory regions. The given word
+ is expanded to full pointer size and searched at aligned as well as
+ un-aligned memory locations. Use 'sa' to search aligned locations
+ only.
+ """
+ try:
+ word = int(word, 0)
+ except ValueError:
+ print "Malformed word, prefix with '0x' to use hexadecimal format."
+ return
+ print "Searching for word %d/0x%s:" % (word,
self.reader.FormatIntPtr(word))
self.reader.FindWord(word)
+ def do_sh(self, none):
+ """
+ Search for the V8 Heap object in all available memory regions. You
+ might get lucky and find this rare treasure full of invaluable
+ information.
+ """
+ raise NotImplementedError
+
def do_list(self, smth):
- """List all available memory regions."""
+ """
+ List all available memory regions.
+ """
def print_region(reader, start, size, location):
- print "%s - %s" % (reader.FormatIntPtr(start),
- reader.FormatIntPtr(start + size))
-
+ print " %s - %s (%d bytes)" % (reader.FormatIntPtr(start),
+ reader.FormatIntPtr(start + size),
+ size)
+ print "Available memory regions:"
self.reader.ForEachMemoryRegion(print_region)
+
+EIP_PROXIMITY = 64
+
+CONTEXT_FOR_ARCH = {
+ MD_CPU_ARCHITECTURE_AMD64:
+ ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'],
+ MD_CPU_ARCHITECTURE_X86:
+ ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
+}
+
+
def AnalyzeMinidump(options, minidump_name):
reader = MinidumpReader(options, minidump_name)
heap = None
@@ -1240,7 +1626,7 @@
heap = V8Heap(reader, None)
if options.full:
- do_dump(reader, heap)
+ FullDump(reader, heap)
if options.shell:
InspectionShell(reader, heap).cmdloop("type help to get help")
@@ -1261,8 +1647,10 @@
if __name__ == "__main__":
parser = optparse.OptionParser(USAGE)
- parser.add_option("-s", "--shell", dest="shell", action="store_true")
- parser.add_option("-f", "--full", dest="full", action="store_true")
+ parser.add_option("-s", "--shell", dest="shell", action="store_true",
+ help="start an interactive inspector shell")
+ parser.add_option("-f", "--full", dest="full", action="store_true",
+ help="dump all information contained in the minidump")
options, args = parser.parse_args()
if len(args) != 1:
parser.print_help()
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev