From 7a93464ca0e155ebc5ffa8fadbef3fa9679f6bcb Mon Sep 17 00:00:00 2001 From: "vegorov@chromium.org" Date: Thu, 15 Dec 2011 12:13:34 +0000 Subject: [PATCH] Add X64 minidumps support to tools/grokdump.py R=erik.corry@gmail.com Review URL: http://codereview.chromium.org/8957005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10263 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- tools/grokdump.py | 328 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 257 insertions(+), 71 deletions(-) diff --git a/tools/grokdump.py b/tools/grokdump.py index 6bc49c6..0c7e125 100755 --- a/tools/grokdump.py +++ b/tools/grokdump.py @@ -52,6 +52,7 @@ Examples: $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp """ + DEBUG=False @@ -233,6 +234,80 @@ MINIDUMP_CONTEXT_X86 = Descriptor([ MD_CONTEXT_X86_EXTENDED_REGISTERS)) ]) +MD_CONTEXT_AMD64 = 0x00100000 +MD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001) +MD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002) +MD_CONTEXT_AMD64_SEGMENTS = (MD_CONTEXT_AMD64 | 0x00000004) +MD_CONTEXT_AMD64_FLOATING_POINT = (MD_CONTEXT_AMD64 | 0x00000008) +MD_CONTEXT_AMD64_DEBUG_REGISTERS = (MD_CONTEXT_AMD64 | 0x00000010) + +MINIDUMP_CONTEXT_AMD64 = Descriptor([ + ("p1_home", ctypes.c_uint64), + ("p2_home", ctypes.c_uint64), + ("p3_home", ctypes.c_uint64), + ("p4_home", ctypes.c_uint64), + ("p5_home", ctypes.c_uint64), + ("p6_home", ctypes.c_uint64), + ("context_flags", ctypes.c_uint32), + ("mx_csr", ctypes.c_uint32), + # MD_CONTEXT_AMD64_CONTROL. + ("cs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)), + # MD_CONTEXT_AMD64_SEGMENTS + ("ds", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)), + ("es", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)), + ("fs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)), + ("gs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)), + # MD_CONTEXT_AMD64_CONTROL. + ("ss", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)), + ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_AMD64_CONTROL)), + # MD_CONTEXT_AMD64_DEBUG_REGISTERS. + ("dr0", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("dr1", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("dr2", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("dr3", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("dr6", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("dr7", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + # MD_CONTEXT_AMD64_INTEGER. + ("rax", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("rcx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("rdx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("rbx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + # MD_CONTEXT_AMD64_CONTROL. + ("rsp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)), + # MD_CONTEXT_AMD64_INTEGER. + ("rbp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("rsi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("rdi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r8", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r9", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r10", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r11", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r12", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r13", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r14", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + ("r15", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)), + # MD_CONTEXT_AMD64_CONTROL. + ("rip", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)), + # MD_CONTEXT_AMD64_FLOATING_POINT + ("sse_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26), + MD_CONTEXT_AMD64_FLOATING_POINT)), + ("vector_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26), + MD_CONTEXT_AMD64_FLOATING_POINT)), + ("vector_control", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_FLOATING_POINT)), + # MD_CONTEXT_AMD64_DEBUG_REGISTERS. + ("debug_control", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("last_branch_to_rip", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("last_branch_from_rip", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("last_exception_to_rip", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_DEBUG_REGISTERS)), + ("last_exception_from_rip", EnableOnFlag(ctypes.c_uint64, + MD_CONTEXT_AMD64_DEBUG_REGISTERS)) +]) + MINIDUMP_MEMORY_DESCRIPTOR = Descriptor([ ("start", ctypes.c_uint64), ("memory", MINIDUMP_LOCATION_DESCRIPTOR.ctype) @@ -269,6 +344,12 @@ MINIDUMP_THREAD_LIST = Descriptor([ ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count) ]) +MINIDUMP_RAW_SYSTEM_INFO = Descriptor([ + ("processor_architecture", ctypes.c_uint16) +]) + +MD_CPU_ARCHITECTURE_X86 = 0 +MD_CPU_ARCHITECTURE_AMD64 = 9 class MinidumpReader(object): """Minidump (.dmp) reader.""" @@ -288,20 +369,34 @@ class MinidumpReader(object): for _ in xrange(self.header.stream_count): directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset)) offset += MINIDUMP_DIRECTORY.size + self.arch = None self.exception = None self.exception_context = None self.memory_list = None self.memory_list64 = None self.thread_map = {} + + # Find MDRawSystemInfo stream and determine arch. + for d in directories: + if d.stream_type == MD_SYSTEM_INFO_STREAM: + system_info = MINIDUMP_RAW_SYSTEM_INFO.Read( + self.minidump, d.location.rva) + self.arch = system_info.processor_architecture + assert self.arch in [MD_CPU_ARCHITECTURE_AMD64, MD_CPU_ARCHITECTURE_X86] + assert not self.arch is None + for d in directories: DebugPrint(d) - # TODO(vitalyr): extract system info including CPU features. if d.stream_type == MD_EXCEPTION_STREAM: self.exception = MINIDUMP_EXCEPTION_STREAM.Read( self.minidump, d.location.rva) DebugPrint(self.exception) - self.exception_context = MINIDUMP_CONTEXT_X86.Read( - self.minidump, self.exception.thread_context.rva) + if self.arch == MD_CPU_ARCHITECTURE_X86: + self.exception_context = MINIDUMP_CONTEXT_X86.Read( + self.minidump, self.exception.thread_context.rva) + elif self.arch == MD_CPU_ARCHITECTURE_AMD64: + self.exception_context = MINIDUMP_CONTEXT_AMD64.Read( + self.minidump, self.exception.thread_context.rva) DebugPrint(self.exception_context) elif d.stream_type == MD_THREAD_LIST_STREAM: thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) @@ -335,6 +430,16 @@ class MinidumpReader(object): location = self.FindLocation(address) return ctypes.c_uint32.from_buffer(self.minidump, location).value + def ReadU64(self, address): + location = self.FindLocation(address) + return ctypes.c_uint64.from_buffer(self.minidump, location).value + + def ReadUIntPtr(self, address): + if self.arch == MD_CPU_ARCHITECTURE_AMD64: + return self.ReadU64(address) + elif self.arch == MD_CPU_ARCHITECTURE_X86: + return self.ReadU32(address) + def ReadBytes(self, address, size): location = self.FindLocation(address) return self.minidump[location:location + size] @@ -355,10 +460,15 @@ class MinidumpReader(object): def GetDisasmLines(self, address, size): location = self.FindLocation(address) if location is None: return [] + arch = None + if self.arch == MD_CPU_ARCHITECTURE_X86: + arch = "ia32" + elif self.arch == MD_CPU_ARCHITECTURE_AMD64: + arch = "x64" return disasm.GetDisasmLines(self.minidump_name, location, size, - "ia32", + arch, False) @@ -366,6 +476,33 @@ class MinidumpReader(object): self.minidump.close() self.minidump_file.close() + def ExceptionIP(self): + if self.arch == MD_CPU_ARCHITECTURE_AMD64: + return self.exception_context.rip + elif self.arch == MD_CPU_ARCHITECTURE_X86: + return self.exception_context.eip + + def ExceptionSP(self): + if self.arch == MD_CPU_ARCHITECTURE_AMD64: + return self.exception_context.rsp + elif self.arch == MD_CPU_ARCHITECTURE_X86: + return self.exception_context.rbp + + def FormatIntPtr(self, value): + if self.arch == MD_CPU_ARCHITECTURE_AMD64: + return "%016x" % value + elif self.arch == MD_CPU_ARCHITECTURE_X86: + return "%08x" % value + + def PointerSize(self): + if self.arch == MD_CPU_ARCHITECTURE_AMD64: + return 8 + elif self.arch == MD_CPU_ARCHITECTURE_X86: + return 4 + + def Register(self, name): + return self.exception_context.__getattribute__(name) + # List of V8 instance types. Obtained by adding the code below to any .cc file. # @@ -501,34 +638,36 @@ class HeapObject(object): p.Print(str(self)) def __str__(self): - return "HeapObject(%08x, %s)" % (self.address, - INSTANCE_TYPES[self.map.instance_type]) + return "HeapObject(%s, %s)" % (self.heap.reader.FormatIntPtr(self.address), + INSTANCE_TYPES[self.map.instance_type]) def ObjectField(self, offset): - field_value = self.heap.reader.ReadU32(self.address + offset) + field_value = self.heap.reader.ReadUIntPtr(self.address + offset) return self.heap.FindObjectOrSmi(field_value) def SmiField(self, offset): - field_value = self.heap.reader.ReadU32(self.address + offset) + field_value = self.heap.reader.ReadUIntPtr(self.address + offset) assert (field_value & 1) == 0 return field_value / 2 class Map(HeapObject): - INSTANCE_TYPE_OFFSET = 8 + def InstanceTypeOffset(): + return self.heap.PointerSize() + self.heap.IntSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) self.instance_type = \ - heap.reader.ReadU8(self.address + Map.INSTANCE_TYPE_OFFSET) + heap.reader.ReadU8(self.address + self.InstanceTypeOffset()) class String(HeapObject): - LENGTH_OFFSET = 4 + def LengthOffset(self): + return self.heap.PointerSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.length = self.SmiField(String.LENGTH_OFFSET) + self.length = self.SmiField(self.LengthOffset()) def GetChars(self): return "?string?" @@ -541,11 +680,12 @@ class String(HeapObject): class SeqString(String): - CHARS_OFFSET = 12 + def CharsOffset(self): + return self.heap.PointerSize() * 3 def __init__(self, heap, map, address): String.__init__(self, heap, map, address) - self.chars = heap.reader.ReadBytes(self.address + SeqString.CHARS_OFFSET, + self.chars = heap.reader.ReadBytes(self.address + self.CharsOffset(), self.length) def GetChars(self): @@ -553,6 +693,7 @@ class SeqString(String): class ExternalString(String): + # TODO(vegorov) fix ExternalString for X64 architecture RESOURCE_OFFSET = 12 WEBKIT_RESOUCE_STRING_IMPL_OFFSET = 4 @@ -582,24 +723,28 @@ class ExternalString(String): class ConsString(String): - LEFT_OFFSET = 12 - RIGHT_OFFSET = 16 + def LeftOffset(self): + return self.heap.PointerSize() * 3 + + def RightOffset(self): + return self.heap.PointerSize() * 4 def __init__(self, heap, map, address): String.__init__(self, heap, map, address) - self.left = self.ObjectField(ConsString.LEFT_OFFSET) - self.right = self.ObjectField(ConsString.RIGHT_OFFSET) + self.left = self.ObjectField(self.LeftOffset()) + self.right = self.ObjectField(self.RightOffset()) def GetChars(self): return self.left.GetChars() + self.right.GetChars() class Oddball(HeapObject): - TO_STRING_OFFSET = 4 + def ToStringOffset(self): + return self.heap.PointerSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.to_string = self.ObjectField(Oddball.TO_STRING_OFFSET) + self.to_string = self.ObjectField(self.ToStringOffset()) def Print(self, p): p.Print(str(self)) @@ -609,19 +754,23 @@ class Oddball(HeapObject): class FixedArray(HeapObject): - LENGTH_OFFSET = 4 - ELEMENTS_OFFSET = 8 + def LengthOffset(self): + return self.heap.PointerSize() + + def ElementsOffset(self): + return self.heap.PointerSize() * 2 def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.length = self.SmiField(FixedArray.LENGTH_OFFSET) + self.length = self.SmiField(self.LengthOffset()) def Print(self, p): - p.Print("FixedArray(%08x) {" % self.address) + p.Print("FixedArray(%s) {" % self.heap.reader.FormatIntPtr(self.address)) p.Indent() p.Print("length: %d" % self.length) + base_offset = self.ElementsOffset() for i in xrange(self.length): - offset = FixedArray.ELEMENTS_OFFSET + 4 * i + offset = base_offset + 4 * i p.Print("[%08d] = %s" % (i, self.ObjectField(offset))) p.Dedent() p.Print("}") @@ -631,19 +780,22 @@ class FixedArray(HeapObject): class JSFunction(HeapObject): - CODE_ENTRY_OFFSET = 12 - SHARED_OFFSET = 20 + def CodeEntryOffset(self): + return 3 * self.heap.PointerSize() + + def SharedOffset(self): + return 5 * self.heap.PointerSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) code_entry = \ - heap.reader.ReadU32(self.address + JSFunction.CODE_ENTRY_OFFSET) - self.code = heap.FindObject(code_entry - Code.ENTRY_OFFSET + 1) - self.shared = self.ObjectField(JSFunction.SHARED_OFFSET) + heap.reader.ReadU32(self.address + self.CodeEntryOffset()) + self.code = heap.FindObject(code_entry - Code.HeaderSize(heap) + 1) + self.shared = self.ObjectField(self.SharedOffset()) def Print(self, p): source = "\n".join(" %s" % line for line in self._GetSource().split("\n")) - p.Print("JSFunction(%08x) {" % self.address) + p.Print("JSFunction(%s) {" % self.heap.reader.FormatIntPtr(self.address)) p.Indent() p.Print("inferred name: %s" % self.shared.inferred_name) if self.shared.script.Is(Script) and self.shared.script.name.Is(String): @@ -662,7 +814,8 @@ class JSFunction(HeapObject): inferred_name = "" if self.shared.Is(SharedFunctionInfo): inferred_name = self.shared.inferred_name - return "JSFunction(%08x, %s)" % (self.address, inferred_name) + return "JSFunction(%s, %s)" % \ + (self.heap.reader.FormatIntPtr(self.address), inferred_name) def _GetSource(self): source = "?source?" @@ -675,47 +828,75 @@ class JSFunction(HeapObject): class SharedFunctionInfo(HeapObject): - CODE_OFFSET = 2 * 4 - SCRIPT_OFFSET = 7 * 4 - INFERRED_NAME_OFFSET = 9 * 4 - START_POSITION_AND_TYPE_OFFSET = 17 * 4 - END_POSITION_OFFSET = 18 * 4 + def CodeOffset(self): + return 2 * self.heap.PointerSize() + + def ScriptOffset(self): + return 7 * self.heap.PointerSize() + + def InferredNameOffset(self): + return 9 * self.heap.PointerSize() + + def EndPositionOffset(self): + return 12 * self.heap.PointerSize() + 4 * self.heap.IntSize() + + def StartPositionAndTypeOffset(self): + return 12 * self.heap.PointerSize() + 5 * self.heap.IntSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.code = self.ObjectField(SharedFunctionInfo.CODE_OFFSET) - self.script = self.ObjectField(SharedFunctionInfo.SCRIPT_OFFSET) - self.inferred_name = \ - self.ObjectField(SharedFunctionInfo.INFERRED_NAME_OFFSET) - start_position_and_type = \ - self.SmiField(SharedFunctionInfo.START_POSITION_AND_TYPE_OFFSET) - self.start_position = start_position_and_type >> 2 - self.end_position = self.SmiField(SharedFunctionInfo.END_POSITION_OFFSET) + self.code = self.ObjectField(self.CodeOffset()) + self.script = self.ObjectField(self.ScriptOffset()) + self.inferred_name = self.ObjectField(self.InferredNameOffset()) + if heap.PointerSize() == 8: + start_position_and_type = \ + heap.reader.ReadU32(self.StartPositionAndTypeOffset()) + self.start_position = start_position_and_type >> 2 + pseudo_smi_end_position = \ + heap.reader.ReadU32(self.EndPositionOffset()) + self.end_position = pseudo_smi_end_position >> 2 + else: + start_position_and_type = \ + self.SmiField(self.StartPositionAndTypeOffset()) + self.start_position = start_position_and_type >> 2 + self.end_position = \ + self.SmiField(self.EndPositionOffset()) class Script(HeapObject): - SOURCE_OFFSET = 4 - NAME_OFFSET = 8 + def SourceOffset(self): + return self.heap.PointerSize() + + def NameOffset(self): + return self.SourceOffset() + self.heap.PointerSize() def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.source = self.ObjectField(Script.SOURCE_OFFSET) - self.name = self.ObjectField(Script.NAME_OFFSET) + self.source = self.ObjectField(self.SourceOffset()) + self.name = self.ObjectField(self.NameOffset()) class Code(HeapObject): - INSTRUCTION_SIZE_OFFSET = 4 - ENTRY_OFFSET = 32 + CODE_ALIGNMENT_MASK = (1 << 5) - 1 + + def InstructionSizeOffset(self): + return self.heap.PointerSize() + + @staticmethod + def HeaderSize(heap): + return (heap.PointerSize() + heap.IntSize() + \ + 4 * heap.PointerSize() + 3 * heap.IntSize() + \ + CODE_ALIGNMENT_MASK) & ~CODE_ALIGNMENT_MASK def __init__(self, heap, map, address): HeapObject.__init__(self, heap, map, address) - self.entry = self.address + Code.ENTRY_OFFSET + self.entry = self.address + Code.HeaderSize(heap) self.instruction_size = \ - heap.reader.ReadU32(self.address + Code.INSTRUCTION_SIZE_OFFSET) + heap.reader.ReadU32(self.address + self.InstructionSizeOffset()) def Print(self, p): lines = self.heap.reader.GetDisasmLines(self.entry, self.instruction_size) - p.Print("Code(%08x) {" % self.address) + p.Print("Code(%s) {" % self.heap.reader.FormatIntPtr(self.address)) p.Indent() p.Print("instruction_size: %d" % self.instruction_size) p.PrintLines(self._FormatLine(line) for line in lines) @@ -767,7 +948,7 @@ class V8Heap(object): if (tagged_address & 1) != 1: return None address = tagged_address - 1 if not self.reader.IsValidAddress(address): return None - map_tagged_address = self.reader.ReadU32(address) + map_tagged_address = self.reader.ReadUIntPtr(address) if tagged_address == map_tagged_address: # Meta map? meta_map = Map(self, None, address) @@ -785,9 +966,19 @@ class V8Heap(object): self.objects[tagged_address] = object return object + def PointerSize(self): + return self.reader.PointerSize() + + 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) @@ -800,40 +991,35 @@ def AnalyzeMinidump(options, minidump_name): print " thread id: %d" % exception_thread.id print " code: %08X" % reader.exception.exception.code print " context:" - print " eax: %08x" % reader.exception_context.eax - print " ebx: %08x" % reader.exception_context.ebx - print " ecx: %08x" % reader.exception_context.ecx - print " edx: %08x" % reader.exception_context.edx - print " edi: %08x" % reader.exception_context.edi - print " esi: %08x" % reader.exception_context.esi - print " ebp: %08x" % reader.exception_context.ebp - print " esp: %08x" % reader.exception_context.esp - print " eip: %08x" % reader.exception_context.eip + for r in CONTEXT_FOR_ARCH[reader.arch]: + print " %s: %s" % (r, reader.FormatIntPtr(reader.Register(r))) # TODO(vitalyr): decode eflags. print " eflags: %s" % bin(reader.exception_context.eflags)[2:] print + stack_top = reader.ExceptionSP() stack_bottom = exception_thread.stack.start + \ exception_thread.stack.memory.data_size - stack_map = {reader.exception_context.eip: -1} - for slot in xrange(reader.exception_context.esp, stack_bottom, 4): - maybe_address = reader.ReadU32(slot) + stack_map = {reader.ExceptionIP(): -1} + for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): + maybe_address = reader.ReadUIntPtr(slot) if not maybe_address in stack_map: stack_map[maybe_address] = slot heap = V8Heap(reader, stack_map) print "Disassembly around exception.eip:" - start = reader.exception_context.eip - EIP_PROXIMITY + start = reader.ExceptionIP() - EIP_PROXIMITY lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY) for line in lines: print FormatDisasmLine(start, heap, line) print print "Annotated stack (from exception.esp to bottom):" - for slot in xrange(reader.exception_context.esp, stack_bottom, 4): - maybe_address = reader.ReadU32(slot) + for slot in xrange(stack_top, stack_bottom, reader.PointerSize()): + maybe_address = reader.ReadUIntPtr(slot) heap_object = heap.FindObject(maybe_address) - print "%08x: %08x" % (slot, maybe_address) + print "%s: %s" % (reader.FormatIntPtr(slot), + reader.FormatIntPtr(maybe_address)) if heap_object: heap_object.Print(Printer()) print -- 2.7.4