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
This commit is contained in:
parent
626b61f967
commit
7a93464ca0
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user