Chromium Code Reviews| Index: tools/grokdump.py |
| diff --git a/tools/grokdump.py b/tools/grokdump.py |
| index 6bc49c68a83dc4fc7fc4d56f4218bf608e224a05..0c7e125e4b6d2dbf63385544db3476a109ee20f6 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) |
|
Erik Corry
2011/12/15 12:09:11
Do we output an error message if it's not one of t
|
| 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:] |
| + 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 "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()) |