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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/grokdump.py
diff --git a/tools/grokdump.py b/tools/grokdump.py
index 407130695a823c58758d914c247155e0c649c52b..2227635d3fa6c9f6a4db75e04304eb212c20410a 100755
--- a/tools/grokdump.py
+++ b/tools/grokdump.py
@@ -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 re
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 @@ class Descriptor(object):
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 @@ class MinidumpReader(object):
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 @@ class MinidumpReader(object):
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 @@ class MinidumpReader(object):
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 @@ INSTANCE_TYPES = {
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) \
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
+# 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 @@ class Oddball(HeapObject):
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 @@ class Script(HeapObject):
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 @@ class V8Heap(object):
"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 @@ class V8Heap(object):
elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
return (1 << 5) - 1
+ def PageAlignmentMask(self):
+ return (1 << 20) - 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']
-}
+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 @@ def AnalyzeMinidump(options, minidump_name):
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 @@ def AnalyzeMinidump(options, minidump_name):
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()
« 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