1e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#!/usr/bin/env python
2e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#
3e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# Copyright 2011 the V8 project authors. All rights reserved.
4e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# Redistribution and use in source and binary forms, with or without
5e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# modification, are permitted provided that the following conditions are
6e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# met:
7e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#
8e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#     * Redistributions of source code must retain the above copyright
9e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       notice, this list of conditions and the following disclaimer.
10e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#     * Redistributions in binary form must reproduce the above
11e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       copyright notice, this list of conditions and the following
12e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       disclaimer in the documentation and/or other materials provided
13e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       with the distribution.
14e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#     * Neither the name of Google Inc. nor the names of its
15e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       contributors may be used to endorse or promote products derived
16e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#       from this software without specific prior written permission.
17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#
18e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport ctypes
31e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport mmap
32e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport optparse
33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport os
34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport disasm
35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport sys
36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport types
37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport codecs
38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport re
39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochUSAGE="""usage: %prog [OPTION]...
42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMinidump analyzer.
44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochShows the processor state at the point of exception including the
46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstack of the active thread and the referenced objects in the V8
47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochheap. Code objects are disassembled and the addresses linked from the
48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstack (pushed return addresses) are marked with "=>".
49e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochExamples:
52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp
53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch"""
54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochDEBUG=False
57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdef DebugPrint(s):
60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if not DEBUG: return
61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print s
62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
63e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Descriptor(object):
65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  """Descriptor of a structure in a memory."""
66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, fields):
68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.fields = fields
69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.is_flexible = False
70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for _, type_or_func in fields:
71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if isinstance(type_or_func, types.FunctionType):
72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        self.is_flexible = True
73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        break
74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not self.is_flexible:
75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      self.ctype = Descriptor._GetCtype(fields)
76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      self.size = ctypes.sizeof(self.ctype)
77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Read(self, memory, offset):
79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if self.is_flexible:
80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      fields_copy = self.fields[:]
81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      last = 0
82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      for name, type_or_func in fields_copy:
83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if isinstance(type_or_func, types.FunctionType):
84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          partial_ctype = Descriptor._GetCtype(fields_copy[:last])
85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          partial_object = partial_ctype.from_buffer(memory, offset)
86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          type = type_or_func(partial_object)
87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          if type is not None:
88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            fields_copy[last] = (name, type)
89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            last += 1
90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        else:
91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          last += 1
92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      complete_ctype = Descriptor._GetCtype(fields_copy[:last])
93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    else:
94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      complete_ctype = self.ctype
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return complete_ctype.from_buffer(memory, offset)
96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  @staticmethod
98e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def _GetCtype(fields):
99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    class Raw(ctypes.Structure):
100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      _fields_ = fields
101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      _pack_ = 1
102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      def __str__(self):
104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field))
105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                               for field, _ in Raw._fields_) + "}"
106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return Raw
107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# Set of structures and constants that describe the layout of minidump
110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# files. Based on MSDN and Google Breakpad.
111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_HEADER = Descriptor([
113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("signature", ctypes.c_uint32),
114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("version", ctypes.c_uint32),
115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("stream_count", ctypes.c_uint32),
116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("stream_directories_rva", ctypes.c_uint32),
117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("checksum", ctypes.c_uint32),
118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("time_date_stampt", ctypes.c_uint32),
119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("flags", ctypes.c_uint64)
120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_LOCATION_DESCRIPTOR = Descriptor([
123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("data_size", ctypes.c_uint32),
124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("rva", ctypes.c_uint32)
125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_DIRECTORY = Descriptor([
128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("stream_type", ctypes.c_uint32),
129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("location", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_EXCEPTION_MAXIMUM_PARAMETERS = 15
133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_EXCEPTION = Descriptor([
135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("code", ctypes.c_uint32),
136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("flags", ctypes.c_uint32),
137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("record", ctypes.c_uint64),
138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("address", ctypes.c_uint64),
139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("parameter_count", ctypes.c_uint32),
140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("unused_alignment", ctypes.c_uint32),
141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("information", ctypes.c_uint64 * MD_EXCEPTION_MAXIMUM_PARAMETERS)
142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_EXCEPTION_STREAM = Descriptor([
145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("thread_id", ctypes.c_uint32),
146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("unused_alignment", ctypes.c_uint32),
147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("exception", MINIDUMP_EXCEPTION.ctype),
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("thread_context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# Stream types.
152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_UNUSED_STREAM = 0
153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_RESERVED_STREAM_0 = 1
154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_RESERVED_STREAM_1 = 2
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_THREAD_LIST_STREAM = 3
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_MODULE_LIST_STREAM = 4
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_MEMORY_LIST_STREAM = 5
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_EXCEPTION_STREAM = 6
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_SYSTEM_INFO_STREAM = 7
160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_THREAD_EX_LIST_STREAM = 8
161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_MEMORY_64_LIST_STREAM = 9
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_COMMENT_STREAM_A = 10
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_COMMENT_STREAM_W = 11
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_HANDLE_DATA_STREAM = 12
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_FUNCTION_TABLE_STREAM = 13
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_UNLOADED_MODULE_LIST_STREAM = 14
167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_MISC_INFO_STREAM = 15
168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_MEMORY_INFO_LIST_STREAM = 16
169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_THREAD_INFO_LIST_STREAM = 17
170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_HANDLE_OPERATION_LIST_STREAM = 18
171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE = 80
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_FLOATING_SAVE_AREA_X86 = Descriptor([
175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("control_word", ctypes.c_uint32),
176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("status_word", ctypes.c_uint32),
177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("tag_word", ctypes.c_uint32),
178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("error_offset", ctypes.c_uint32),
179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("error_selector", ctypes.c_uint32),
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("data_offset", ctypes.c_uint32),
181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("data_selector", ctypes.c_uint32),
182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("register_area", ctypes.c_uint8 * MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE),
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("cr0_npx_state", ctypes.c_uint32)
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE = 512
187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# Context flags.
189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86 = 0x00010000
190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_CONTROL = (MD_CONTEXT_X86 | 0x00000001)
191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_INTEGER = (MD_CONTEXT_X86 | 0x00000002)
192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_SEGMENTS = (MD_CONTEXT_X86 | 0x00000004)
193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_FLOATING_POINT = (MD_CONTEXT_X86 | 0x00000008)
194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_DEBUG_REGISTERS = (MD_CONTEXT_X86 | 0x00000010)
195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMD_CONTEXT_X86_EXTENDED_REGISTERS = (MD_CONTEXT_X86 | 0x00000020)
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdef EnableOnFlag(type, flag):
198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return lambda o: [None, type][int((o.context_flags & flag) != 0)]
199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_CONTEXT_X86 = Descriptor([
201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("context_flags", ctypes.c_uint32),
202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_DEBUG_REGISTERS.
203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr0", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr1", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr2", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr3", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr6", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("dr7", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_FLOATING_POINT.
210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_X86.ctype,
211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              MD_CONTEXT_X86_FLOATING_POINT)),
212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_SEGMENTS.
213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("gs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("fs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("es", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ds", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_INTEGER.
218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("edi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("esi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ebx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("edx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ecx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("eax", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_CONTROL.
225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ebp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("eip", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("cs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("esp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ss", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # MD_CONTEXT_X86_EXTENDED_REGISTERS.
232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("extended_registers",
233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch   EnableOnFlag(ctypes.c_uint8 * MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE,
234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                MD_CONTEXT_X86_EXTENDED_REGISTERS))
235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64 = 0x00100000
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001)
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002)
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64_SEGMENTS = (MD_CONTEXT_AMD64 | 0x00000004)
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64_FLOATING_POINT = (MD_CONTEXT_AMD64 | 0x00000008)
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CONTEXT_AMD64_DEBUG_REGISTERS = (MD_CONTEXT_AMD64 | 0x00000010)
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMINIDUMP_CONTEXT_AMD64 = Descriptor([
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p1_home", ctypes.c_uint64),
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p2_home", ctypes.c_uint64),
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p3_home", ctypes.c_uint64),
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p4_home", ctypes.c_uint64),
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p5_home", ctypes.c_uint64),
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("p6_home", ctypes.c_uint64),
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("context_flags", ctypes.c_uint32),
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("mx_csr", ctypes.c_uint32),
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_CONTROL.
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("cs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)),
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_SEGMENTS
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("ds", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("es", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("fs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("gs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_CONTROL.
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("ss", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)),
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_AMD64_CONTROL)),
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_DEBUG_REGISTERS.
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr0", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr1", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr2", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr3", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr6", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("dr7", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_INTEGER.
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rax", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rcx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rdx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rbx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_CONTROL.
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rsp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)),
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_INTEGER.
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rbp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rsi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rdi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r8", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r9", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r10", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r11", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r12", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r13", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r14", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("r15", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_CONTROL.
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("rip", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)),
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_FLOATING_POINT
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("sse_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26),
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 MD_CONTEXT_AMD64_FLOATING_POINT)),
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("vector_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26),
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    MD_CONTEXT_AMD64_FLOATING_POINT)),
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("vector_control", EnableOnFlag(ctypes.c_uint64,
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  MD_CONTEXT_AMD64_FLOATING_POINT)),
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # MD_CONTEXT_AMD64_DEBUG_REGISTERS.
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("debug_control", EnableOnFlag(ctypes.c_uint64,
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("last_branch_to_rip", EnableOnFlag(ctypes.c_uint64,
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("last_branch_from_rip", EnableOnFlag(ctypes.c_uint64,
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("last_exception_to_rip", EnableOnFlag(ctypes.c_uint64,
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("last_exception_from_rip", EnableOnFlag(ctypes.c_uint64,
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           MD_CONTEXT_AMD64_DEBUG_REGISTERS))
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch])
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_MEMORY_DESCRIPTOR = Descriptor([
312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("start", ctypes.c_uint64),
313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("memory", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_MEMORY_DESCRIPTOR64 = Descriptor([
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("start", ctypes.c_uint64),
318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("size", ctypes.c_uint64)
319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_MEMORY_LIST = Descriptor([
322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("range_count", ctypes.c_uint32),
323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR.ctype * m.range_count)
324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_MEMORY_LIST64 = Descriptor([
327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("range_count", ctypes.c_uint64),
328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("base_rva", ctypes.c_uint64),
329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR64.ctype * m.range_count)
330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_THREAD = Descriptor([
333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("id", ctypes.c_uint32),
334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("suspend_count", ctypes.c_uint32),
335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("priority_class", ctypes.c_uint32),
336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("priority", ctypes.c_uint32),
337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("ted", ctypes.c_uint64),
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("stack", MINIDUMP_MEMORY_DESCRIPTOR.ctype),
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMINIDUMP_THREAD_LIST = Descriptor([
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("thread_count", ctypes.c_uint32),
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch])
346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMINIDUMP_RAW_SYSTEM_INFO = Descriptor([
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ("processor_architecture", ctypes.c_uint16)
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch])
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CPU_ARCHITECTURE_X86 = 0
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMD_CPU_ARCHITECTURE_AMD64 = 9
353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass MinidumpReader(object):
355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  """Minidump (.dmp) reader."""
356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  _HEADER_MAGIC = 0x504d444d
358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, options, minidump_name):
360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.minidump_name = minidump_name
361e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.minidump_file = open(minidump_name, "r")
362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE)
363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if self.header.signature != MinidumpReader._HEADER_MAGIC:
365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      print >>sys.stderr, "Warning: unsupported minidump header magic"
366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    DebugPrint(self.header)
367e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    directories = []
368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    offset = self.header.stream_directories_rva
369e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for _ in xrange(self.header.stream_count):
370e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset))
371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      offset += MINIDUMP_DIRECTORY.size
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.arch = None
373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.exception = None
374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.exception_context = None
375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.memory_list = None
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    self.memory_list64 = None
377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.thread_map = {}
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    # Find MDRawSystemInfo stream and determine arch.
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for d in directories:
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if d.stream_type == MD_SYSTEM_INFO_STREAM:
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        system_info = MINIDUMP_RAW_SYSTEM_INFO.Read(
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            self.minidump, d.location.rva)
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        self.arch = system_info.processor_architecture
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assert self.arch in [MD_CPU_ARCHITECTURE_AMD64, MD_CPU_ARCHITECTURE_X86]
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    assert not self.arch is None
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for d in directories:
389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      DebugPrint(d)
390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if d.stream_type == MD_EXCEPTION_STREAM:
391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        self.exception = MINIDUMP_EXCEPTION_STREAM.Read(
392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          self.minidump, d.location.rva)
393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DebugPrint(self.exception)
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if self.arch == MD_CPU_ARCHITECTURE_X86:
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          self.exception_context = MINIDUMP_CONTEXT_X86.Read(
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              self.minidump, self.exception.thread_context.rva)
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          self.exception_context = MINIDUMP_CONTEXT_AMD64.Read(
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              self.minidump, self.exception.thread_context.rva)
400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DebugPrint(self.exception_context)
401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      elif d.stream_type == MD_THREAD_LIST_STREAM:
402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        assert ctypes.sizeof(thread_list) == d.location.data_size
404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DebugPrint(thread_list)
405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        for thread in thread_list.threads:
406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          DebugPrint(thread)
407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          self.thread_map[thread.id] = thread
408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      elif d.stream_type == MD_MEMORY_LIST_STREAM:
409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        print >>sys.stderr, "Warning: not a full minidump"
410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        assert self.memory_list is None
4113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        self.memory_list = MINIDUMP_MEMORY_LIST.Read(
412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          self.minidump, d.location.rva)
413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        assert ctypes.sizeof(self.memory_list) == d.location.data_size
414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        DebugPrint(self.memory_list)
4153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        assert self.memory_list64 is None
4173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read(
4183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          self.minidump, d.location.rva)
4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        assert ctypes.sizeof(self.memory_list64) == d.location.data_size
4203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        DebugPrint(self.memory_list64)
421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def IsValidAddress(self, address):
423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.FindLocation(address) is not None
424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def ReadU8(self, address):
426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    location = self.FindLocation(address)
427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return ctypes.c_uint8.from_buffer(self.minidump, location).value
428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def ReadU32(self, address):
430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    location = self.FindLocation(address)
431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return ctypes.c_uint32.from_buffer(self.minidump, location).value
432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ReadU64(self, address):
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    location = self.FindLocation(address)
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ctypes.c_uint64.from_buffer(self.minidump, location).value
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ReadUIntPtr(self, address):
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.ReadU64(address)
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_X86:
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.ReadU32(address)
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def ReadBytes(self, address, size):
444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    location = self.FindLocation(address)
445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.minidump[location:location + size]
446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def FindLocation(self, address):
448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    offset = 0
4493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if self.memory_list64 is not None:
4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for r in self.memory_list64.ranges:
4513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if r.start <= address < r.start + r.size:
4523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return self.memory_list64.base_rva + offset + address - r.start
45369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        offset += r.size
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if self.memory_list is not None:
4553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for r in self.memory_list.ranges:
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if r.start <= address < r.start + r.memory.data_size:
4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return r.memory.rva + address - r.start
458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return None
459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def GetDisasmLines(self, address, size):
461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    location = self.FindLocation(address)
462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if location is None: return []
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    arch = None
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_X86:
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      arch = "ia32"
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      arch = "x64"
468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return disasm.GetDisasmLines(self.minidump_name,
469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 location,
470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 size,
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 arch,
472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                 False)
473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Dispose(self):
476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.minidump.close()
477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.minidump_file.close()
478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ExceptionIP(self):
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.exception_context.rip
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_X86:
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.exception_context.eip
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ExceptionSP(self):
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.exception_context.rsp
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_X86:
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return self.exception_context.esp
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def FormatIntPtr(self, value):
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return "%016x" % value
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_X86:
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return "%08x" % value
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def PointerSize(self):
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return 8
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.arch == MD_CPU_ARCHITECTURE_X86:
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return 4
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def Register(self, name):
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.exception_context.__getattribute__(name)
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# List of V8 instance types. Obtained by adding the code below to any .cc file.
508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch# #define DUMP_TYPE(T) printf("  %d: \"%s\",\n", T, #T);
510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# struct P {
511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#   P() {
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#     printf("INSTANCE_TYPES = {\n");
513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#     INSTANCE_TYPE_LIST(DUMP_TYPE)
514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#     printf("}\n");
515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#   }
516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# };
517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch# static P p;
518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochINSTANCE_TYPES = {
51969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  64: "SYMBOL_TYPE",
52069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  68: "ASCII_SYMBOL_TYPE",
52169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  65: "CONS_SYMBOL_TYPE",
52269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  69: "CONS_ASCII_SYMBOL_TYPE",
52369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  66: "EXTERNAL_SYMBOL_TYPE",
52469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  74: "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
52569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  70: "EXTERNAL_ASCII_SYMBOL_TYPE",
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  82: "SHORT_EXTERNAL_SYMBOL_TYPE",
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  90: "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  86: "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE",
52969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  0: "STRING_TYPE",
53069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  4: "ASCII_STRING_TYPE",
53169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  1: "CONS_STRING_TYPE",
53269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  5: "CONS_ASCII_STRING_TYPE",
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  3: "SLICED_STRING_TYPE",
53469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  2: "EXTERNAL_STRING_TYPE",
53569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
53669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  6: "EXTERNAL_ASCII_STRING_TYPE",
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  18: "SHORT_EXTERNAL_STRING_TYPE",
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  26: "SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  22: "SHORT_EXTERNAL_ASCII_STRING_TYPE",
54069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  6: "PRIVATE_EXTERNAL_ASCII_STRING_TYPE",
54169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  128: "MAP_TYPE",
54269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  129: "CODE_TYPE",
54369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  130: "ODDBALL_TYPE",
54469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  131: "JS_GLOBAL_PROPERTY_CELL_TYPE",
54569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  132: "HEAP_NUMBER_TYPE",
54669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  133: "FOREIGN_TYPE",
54769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  134: "BYTE_ARRAY_TYPE",
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  135: "FREE_SPACE_TYPE",
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  136: "EXTERNAL_BYTE_ARRAY_TYPE",
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  137: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  138: "EXTERNAL_SHORT_ARRAY_TYPE",
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  139: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  140: "EXTERNAL_INT_ARRAY_TYPE",
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  141: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  142: "EXTERNAL_FLOAT_ARRAY_TYPE",
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  144: "EXTERNAL_PIXEL_ARRAY_TYPE",
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  146: "FILLER_TYPE",
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  147: "ACCESSOR_INFO_TYPE",
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  148: "ACCESSOR_PAIR_TYPE",
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  149: "ACCESS_CHECK_INFO_TYPE",
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  150: "INTERCEPTOR_INFO_TYPE",
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  151: "CALL_HANDLER_INFO_TYPE",
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  152: "FUNCTION_TEMPLATE_INFO_TYPE",
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  153: "OBJECT_TEMPLATE_INFO_TYPE",
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  154: "SIGNATURE_INFO_TYPE",
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  155: "TYPE_SWITCH_INFO_TYPE",
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  156: "SCRIPT_TYPE",
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  157: "CODE_CACHE_TYPE",
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  158: "POLYMORPHIC_CODE_CACHE_TYPE",
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  161: "FIXED_ARRAY_TYPE",
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  145: "FIXED_DOUBLE_ARRAY_TYPE",
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  162: "SHARED_FUNCTION_INFO_TYPE",
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  163: "JS_MESSAGE_OBJECT_TYPE",
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  166: "JS_VALUE_TYPE",
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  167: "JS_OBJECT_TYPE",
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  168: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  169: "JS_GLOBAL_OBJECT_TYPE",
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  170: "JS_BUILTINS_OBJECT_TYPE",
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  171: "JS_GLOBAL_PROXY_TYPE",
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  172: "JS_ARRAY_TYPE",
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  165: "JS_PROXY_TYPE",
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  175: "JS_WEAK_MAP_TYPE",
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  176: "JS_REGEXP_TYPE",
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  177: "JS_FUNCTION_TYPE",
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  164: "JS_FUNCTION_PROXY_TYPE",
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  159: "DEBUG_INFO_TYPE",
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  160: "BREAK_POINT_INFO_TYPE",
588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Printer(object):
592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  """Printer with indentation support."""
593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self):
595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.indent = 0
596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Indent(self):
598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.indent += 2
599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Dedent(self):
601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.indent -= 2
602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, string):
604e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    print "%s%s" % (self._IndentString(), string)
605e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
606e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def PrintLines(self, lines):
607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    indent = self._IndentString()
608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    print "\n".join("%s%s" % (indent, line) for line in lines)
609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def _IndentString(self):
611e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.indent * " "
612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
613e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochADDRESS_RE = re.compile(r"0x[0-9a-fA-F]+")
615e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdef FormatDisasmLine(start, heap, line):
618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  line_address = start + line[0]
619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  stack_slot = heap.stack_map.get(line_address)
620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  marker = "  "
621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if stack_slot:
622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    marker = "=>"
623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  code = AnnotateAddresses(heap, line[1])
624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return "%s%08x %08x: %s" % (marker, line_address, line[0], code)
625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdef AnnotateAddresses(heap, line):
628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  extra = []
629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for m in ADDRESS_RE.finditer(line):
630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    maybe_address = int(m.group(0), 16)
631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    object = heap.FindObject(maybe_address)
632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not object: continue
633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    extra.append(str(object))
634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if len(extra) == 0: return line
635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return "%s  ;; %s" % (line, ", ".join(extra))
636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
637e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass HeapObject(object):
639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.heap = heap
641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.map = map
642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.address = address
643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Is(self, cls):
645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return isinstance(self, cls)
646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print(str(self))
649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __str__(self):
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return "HeapObject(%s, %s)" % (self.heap.reader.FormatIntPtr(self.address),
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   INSTANCE_TYPES[self.map.instance_type])
653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def ObjectField(self, offset):
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.heap.FindObjectOrSmi(field_value)
657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def SmiField(self, offset):
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    field_value = self.heap.reader.ReadUIntPtr(self.address + offset)
660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    assert (field_value & 1) == 0
661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return field_value / 2
662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Map(HeapObject):
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def InstanceTypeOffset(self):
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize() + self.heap.IntSize()
667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.instance_type = \
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        heap.reader.ReadU8(self.address + self.InstanceTypeOffset())
672e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass String(HeapObject):
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def LengthOffset(self):
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize()
677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.length = self.SmiField(self.LengthOffset())
681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def GetChars(self):
683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return "?string?"
684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print(str(self))
687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __str__(self):
689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return "\"%s\"" % self.GetChars()
690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass SeqString(String):
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def CharsOffset(self):
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize() * 3
695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    String.__init__(self, heap, map, address)
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.chars = heap.reader.ReadBytes(self.address + self.CharsOffset(),
699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                       self.length)
700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def GetChars(self):
702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.chars
703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass ExternalString(String):
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  # TODO(vegorov) fix ExternalString for X64 architecture
707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  RESOURCE_OFFSET = 12
708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  WEBKIT_RESOUCE_STRING_IMPL_OFFSET = 4
710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  WEBKIT_STRING_IMPL_CHARS_OFFSET = 8
711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    String.__init__(self, heap, map, address)
714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    reader = heap.reader
715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.resource = \
716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        reader.ReadU32(self.address + ExternalString.RESOURCE_OFFSET)
717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.chars = "?external string?"
718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not reader.IsValidAddress(self.resource): return
719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    string_impl_address = self.resource + \
720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ExternalString.WEBKIT_RESOUCE_STRING_IMPL_OFFSET
721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not reader.IsValidAddress(string_impl_address): return
722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    string_impl = reader.ReadU32(string_impl_address)
723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    chars_ptr_address = string_impl + \
724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ExternalString.WEBKIT_STRING_IMPL_CHARS_OFFSET
725e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not reader.IsValidAddress(chars_ptr_address): return
726e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    chars_ptr = reader.ReadU32(chars_ptr_address)
727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not reader.IsValidAddress(chars_ptr): return
728e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    raw_chars = reader.ReadBytes(chars_ptr, 2 * self.length)
729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.chars = codecs.getdecoder("utf16")(raw_chars)[0]
730e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def GetChars(self):
732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.chars
733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass ConsString(String):
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def LeftOffset(self):
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize() * 3
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def RightOffset(self):
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize() * 4
741e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    String.__init__(self, heap, map, address)
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.left = self.ObjectField(self.LeftOffset())
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.right = self.ObjectField(self.RightOffset())
746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def GetChars(self):
748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.left.GetChars() + self.right.GetChars()
749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Oddball(HeapObject):
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ToStringOffset(self):
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize()
754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.to_string = self.ObjectField(self.ToStringOffset())
758e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print(str(self))
761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __str__(self):
763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return "<%s>" % self.to_string.GetChars()
764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass FixedArray(HeapObject):
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def LengthOffset(self):
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize()
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ElementsOffset(self):
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize() * 2
772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.length = self.SmiField(self.LengthOffset())
776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    p.Print("FixedArray(%s) {" % self.heap.reader.FormatIntPtr(self.address))
779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Indent()
780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("length: %d" % self.length)
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    base_offset = self.ElementsOffset()
782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for i in xrange(self.length):
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      offset = base_offset + 4 * i
784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      p.Print("[%08d] = %s" % (i, self.ObjectField(offset)))
785e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Dedent()
786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("}")
787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __str__(self):
789e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return "FixedArray(%08x, length=%d)" % (self.address, self.length)
790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass JSFunction(HeapObject):
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def CodeEntryOffset(self):
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 3 * self.heap.PointerSize()
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def SharedOffset(self):
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 5 * self.heap.PointerSize()
798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    code_entry = \
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        heap.reader.ReadU32(self.address + self.CodeEntryOffset())
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.code = heap.FindObject(code_entry - Code.HeaderSize(heap) + 1)
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.shared = self.ObjectField(self.SharedOffset())
805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    source = "\n".join("  %s" % line for line in self._GetSource().split("\n"))
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    p.Print("JSFunction(%s) {" % self.heap.reader.FormatIntPtr(self.address))
809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Indent()
810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("inferred name: %s" % self.shared.inferred_name)
811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if self.shared.script.Is(Script) and self.shared.script.name.Is(String):
812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      p.Print("script name: %s" % self.shared.script.name)
813e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("source:")
814e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.PrintLines(self._GetSource().split("\n"))
815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("code:")
816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.code.Print(p)
817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if self.code != self.shared.code:
818e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      p.Print("unoptimized code:")
819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      self.shared.code.Print(p)
820e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Dedent()
821e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("}")
822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __str__(self):
824e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    inferred_name = ""
825e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if self.shared.Is(SharedFunctionInfo):
826e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      inferred_name = self.shared.inferred_name
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return "JSFunction(%s, %s)" % \
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          (self.heap.reader.FormatIntPtr(self.address), inferred_name)
829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
830e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def _GetSource(self):
831e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    source = "?source?"
832e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    start = self.shared.start_position
833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    end = self.shared.end_position
834e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not self.shared.script.Is(Script): return source
835e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    script_source = self.shared.script.source
836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not script_source.Is(String): return source
837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return script_source.GetChars()[start:end]
838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
839e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass SharedFunctionInfo(HeapObject):
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def CodeOffset(self):
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 2 * self.heap.PointerSize()
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ScriptOffset(self):
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 7 * self.heap.PointerSize()
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def InferredNameOffset(self):
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 9 * self.heap.PointerSize()
8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def EndPositionOffset(self):
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 12 * self.heap.PointerSize() + 4 * self.heap.IntSize()
8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def StartPositionAndTypeOffset(self):
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 12 * self.heap.PointerSize() + 5 * self.heap.IntSize()
855e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
857e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.code = self.ObjectField(self.CodeOffset())
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.script = self.ObjectField(self.ScriptOffset())
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.inferred_name = self.ObjectField(self.InferredNameOffset())
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if heap.PointerSize() == 8:
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      start_position_and_type = \
8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          heap.reader.ReadU32(self.StartPositionAndTypeOffset())
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      self.start_position = start_position_and_type >> 2
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      pseudo_smi_end_position = \
8663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          heap.reader.ReadU32(self.EndPositionOffset())
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      self.end_position = pseudo_smi_end_position >> 2
8683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    else:
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      start_position_and_type = \
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          self.SmiField(self.StartPositionAndTypeOffset())
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      self.start_position = start_position_and_type >> 2
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      self.end_position = \
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          self.SmiField(self.EndPositionOffset())
874e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
875e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
876e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Script(HeapObject):
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def SourceOffset(self):
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize()
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def NameOffset(self):
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.SourceOffset() + self.heap.PointerSize()
882e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
883e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
884e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.source = self.ObjectField(self.SourceOffset())
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.name = self.ObjectField(self.NameOffset())
887e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Code(HeapObject):
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CODE_ALIGNMENT_MASK = (1 << 5) - 1
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def InstructionSizeOffset(self):
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.heap.PointerSize()
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  @staticmethod
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def HeaderSize(heap):
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return (heap.PointerSize() + heap.IntSize() + \
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        4 * heap.PointerSize() + 3 * heap.IntSize() + \
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Code.CODE_ALIGNMENT_MASK) & ~Code.CODE_ALIGNMENT_MASK
900e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
901e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, heap, map, address):
902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject.__init__(self, heap, map, address)
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    self.entry = self.address + Code.HeaderSize(heap)
904e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.instruction_size = \
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        heap.reader.ReadU32(self.address + self.InstructionSizeOffset())
906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def Print(self, p):
908e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    lines = self.heap.reader.GetDisasmLines(self.entry, self.instruction_size)
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    p.Print("Code(%s) {" % self.heap.reader.FormatIntPtr(self.address))
910e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Indent()
911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("instruction_size: %d" % self.instruction_size)
912e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.PrintLines(self._FormatLine(line) for line in lines)
913e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Dedent()
914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    p.Print("}")
915e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
916e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def _FormatLine(self, line):
917e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return FormatDisasmLine(self.entry, self.heap, line)
918e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
919e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
920e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass V8Heap(object):
921e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  CLASS_MAP = {
922e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "SYMBOL_TYPE": SeqString,
923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "ASCII_SYMBOL_TYPE": SeqString,
924e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "CONS_SYMBOL_TYPE": ConsString,
925e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "CONS_ASCII_SYMBOL_TYPE": ConsString,
926e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_SYMBOL_TYPE": ExternalString,
927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
928e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "SHORT_EXTERNAL_SYMBOL_TYPE": ExternalString,
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
932e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "STRING_TYPE": SeqString,
933e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "ASCII_STRING_TYPE": SeqString,
934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "CONS_STRING_TYPE": ConsString,
935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "CONS_ASCII_STRING_TYPE": ConsString,
936e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_STRING_TYPE": ExternalString,
937e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE": ExternalString,
938e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "EXTERNAL_ASCII_STRING_TYPE": ExternalString,
939e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "MAP_TYPE": Map,
941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "ODDBALL_TYPE": Oddball,
942e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "FIXED_ARRAY_TYPE": FixedArray,
943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "JS_FUNCTION_TYPE": JSFunction,
944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo,
945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "SCRIPT_TYPE": Script,
946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    "CODE_TYPE": Code
947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def __init__(self, reader, stack_map):
950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.reader = reader
951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.stack_map = stack_map
952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.objects = {}
953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def FindObjectOrSmi(self, tagged_address):
955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (tagged_address & 1) == 0: return tagged_address / 2
956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return self.FindObject(tagged_address)
957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  def FindObject(self, tagged_address):
959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if tagged_address in self.objects:
960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      return self.objects[tagged_address]
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (tagged_address & self.ObjectAlignmentMask()) != 1: return None
962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    address = tagged_address - 1
963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not self.reader.IsValidAddress(address): return None
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    map_tagged_address = self.reader.ReadUIntPtr(address)
965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if tagged_address == map_tagged_address:
966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      # Meta map?
967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      meta_map = Map(self, None, address)
968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      instance_type_name = INSTANCE_TYPES.get(meta_map.instance_type)
969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if instance_type_name != "MAP_TYPE": return None
970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      meta_map.map = meta_map
971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      object = meta_map
972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    else:
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      map = self.FindMap(map_tagged_address)
974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if map is None: return None
975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      instance_type_name = INSTANCE_TYPES.get(map.instance_type)
976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if instance_type_name is None: return None
977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      object = cls(self, map, address)
979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    self.objects[tagged_address] = object
980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return object
981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def FindMap(self, tagged_address):
9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (tagged_address & self.MapAlignmentMask()) != 1: return None
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    address = tagged_address - 1
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if not self.reader.IsValidAddress(address): return None
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    object = Map(self, None, address)
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return object
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def IntSize(self):
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 4
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def PointerSize(self):
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.reader.PointerSize()
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def ObjectAlignmentMask(self):
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return self.PointerSize() - 1
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  def MapAlignmentMask(self):
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64:
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return (1 << 4) - 1
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return (1 << 5) - 1
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1004e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochEIP_PROXIMITY = 64
1006e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCONTEXT_FOR_ARCH = {
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MD_CPU_ARCHITECTURE_AMD64:
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip'],
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MD_CPU_ARCHITECTURE_X86:
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdef AnalyzeMinidump(options, minidump_name):
1015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  reader = MinidumpReader(options, minidump_name)
1016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DebugPrint("========================================")
1017e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if reader.exception is None:
1018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    print "Minidump has no exception info"
1019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return
1020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "Exception info:"
1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  exception_thread = reader.thread_map[reader.exception.thread_id]
1022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "  thread id: %d" % exception_thread.id
1023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "  code: %08X" % reader.exception.exception.code
1024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "  context:"
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for r in CONTEXT_FOR_ARCH[reader.arch]:
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    print "    %s: %s" % (r, reader.FormatIntPtr(reader.Register(r)))
1027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  # TODO(vitalyr): decode eflags.
1028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "    eflags: %s" % bin(reader.exception_context.eflags)[2:]
1029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print
1030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  stack_top = reader.ExceptionSP()
1032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  stack_bottom = exception_thread.stack.start + \
1033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      exception_thread.stack.memory.data_size
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  stack_map = {reader.ExceptionIP(): -1}
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    maybe_address = reader.ReadUIntPtr(slot)
1037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if not maybe_address in stack_map:
1038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      stack_map[maybe_address] = slot
1039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  heap = V8Heap(reader, stack_map)
1040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "Disassembly around exception.eip:"
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  start = reader.ExceptionIP() - EIP_PROXIMITY
1043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  lines = reader.GetDisasmLines(start, 2 * EIP_PROXIMITY)
1044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for line in lines:
1045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    print FormatDisasmLine(start, heap, line)
1046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print
1047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  print "Annotated stack (from exception.esp to bottom):"
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    maybe_address = reader.ReadUIntPtr(slot)
1051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    heap_object = heap.FindObject(maybe_address)
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    print "%s: %s" % (reader.FormatIntPtr(slot),
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      reader.FormatIntPtr(maybe_address))
1054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if heap_object:
1055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      heap_object.Print(Printer())
1056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      print
1057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  reader.Dispose()
1059e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochif __name__ == "__main__":
1062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  parser = optparse.OptionParser(USAGE)
1063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  options, args = parser.parse_args()
1064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if len(args) != 1:
1065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    parser.print_help()
1066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    sys.exit(1)
1067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AnalyzeMinidump(options, args[0])
1068