11cb0ef41Sopenharmony_ci#!/usr/bin/env python3
21cb0ef41Sopenharmony_ci#
31cb0ef41Sopenharmony_ci# Copyright 2012 the V8 project authors. All rights reserved.
41cb0ef41Sopenharmony_ci# Redistribution and use in source and binary forms, with or without
51cb0ef41Sopenharmony_ci# modification, are permitted provided that the following conditions are
61cb0ef41Sopenharmony_ci# met:
71cb0ef41Sopenharmony_ci#
81cb0ef41Sopenharmony_ci#     * Redistributions of source code must retain the above copyright
91cb0ef41Sopenharmony_ci#       notice, this list of conditions and the following disclaimer.
101cb0ef41Sopenharmony_ci#     * Redistributions in binary form must reproduce the above
111cb0ef41Sopenharmony_ci#       copyright notice, this list of conditions and the following
121cb0ef41Sopenharmony_ci#       disclaimer in the documentation and/or other materials provided
131cb0ef41Sopenharmony_ci#       with the distribution.
141cb0ef41Sopenharmony_ci#     * Neither the name of Google Inc. nor the names of its
151cb0ef41Sopenharmony_ci#       contributors may be used to endorse or promote products derived
161cb0ef41Sopenharmony_ci#       from this software without specific prior written permission.
171cb0ef41Sopenharmony_ci#
181cb0ef41Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
191cb0ef41Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
201cb0ef41Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
211cb0ef41Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
221cb0ef41Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
231cb0ef41Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
241cb0ef41Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
251cb0ef41Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
261cb0ef41Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
271cb0ef41Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
281cb0ef41Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci# flake8: noqa  # https://bugs.chromium.org/p/v8/issues/detail?id=8784
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciimport http.server as http_server
341cb0ef41Sopenharmony_ciimport bisect
351cb0ef41Sopenharmony_ciimport html
361cb0ef41Sopenharmony_ciimport cmd
371cb0ef41Sopenharmony_ciimport codecs
381cb0ef41Sopenharmony_ciimport ctypes
391cb0ef41Sopenharmony_ciimport datetime
401cb0ef41Sopenharmony_ciimport disasm
411cb0ef41Sopenharmony_ciimport inspect
421cb0ef41Sopenharmony_ciimport mmap
431cb0ef41Sopenharmony_ciimport optparse
441cb0ef41Sopenharmony_ciimport os
451cb0ef41Sopenharmony_ciimport re
461cb0ef41Sopenharmony_ciimport io
471cb0ef41Sopenharmony_ciimport sys
481cb0ef41Sopenharmony_ciimport types
491cb0ef41Sopenharmony_ciimport urllib.parse
501cb0ef41Sopenharmony_ciimport v8heapconst
511cb0ef41Sopenharmony_ciimport webbrowser
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciPORT_NUMBER = 8081
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciUSAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ciMinidump analyzer.
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciShows the processor state at the point of exception including the
611cb0ef41Sopenharmony_cistack of the active thread and the referenced objects in the V8
621cb0ef41Sopenharmony_ciheap. Code objects are disassembled and the addresses linked from the
631cb0ef41Sopenharmony_cistack (e.g. pushed return addresses) are marked with "=>".
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciExamples:
661cb0ef41Sopenharmony_ci  $ %prog 12345678-1234-1234-1234-123456789abcd-full.dmp"""
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciDEBUG=False
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cidef DebugPrint(s):
731cb0ef41Sopenharmony_ci  if not DEBUG: return
741cb0ef41Sopenharmony_ci  print(s)
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciclass Descriptor(object):
781cb0ef41Sopenharmony_ci  """Descriptor of a structure in a memory."""
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  def __init__(self, fields):
811cb0ef41Sopenharmony_ci    self.fields = fields
821cb0ef41Sopenharmony_ci    self.is_flexible = False
831cb0ef41Sopenharmony_ci    for _, type_or_func in fields:
841cb0ef41Sopenharmony_ci      if isinstance(type_or_func, types.FunctionType):
851cb0ef41Sopenharmony_ci        self.is_flexible = True
861cb0ef41Sopenharmony_ci        break
871cb0ef41Sopenharmony_ci    if not self.is_flexible:
881cb0ef41Sopenharmony_ci      self.ctype = Descriptor._GetCtype(fields)
891cb0ef41Sopenharmony_ci      self.size = ctypes.sizeof(self.ctype)
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  def Read(self, memory, offset):
921cb0ef41Sopenharmony_ci    if self.is_flexible:
931cb0ef41Sopenharmony_ci      fields_copy = self.fields[:]
941cb0ef41Sopenharmony_ci      last = 0
951cb0ef41Sopenharmony_ci      for name, type_or_func in fields_copy:
961cb0ef41Sopenharmony_ci        if isinstance(type_or_func, types.FunctionType):
971cb0ef41Sopenharmony_ci          partial_ctype = Descriptor._GetCtype(fields_copy[:last])
981cb0ef41Sopenharmony_ci          partial_object = partial_ctype.from_buffer(memory, offset)
991cb0ef41Sopenharmony_ci          type = type_or_func(partial_object)
1001cb0ef41Sopenharmony_ci          if type is not None:
1011cb0ef41Sopenharmony_ci            fields_copy[last] = (name, type)
1021cb0ef41Sopenharmony_ci            last += 1
1031cb0ef41Sopenharmony_ci        else:
1041cb0ef41Sopenharmony_ci          last += 1
1051cb0ef41Sopenharmony_ci      complete_ctype = Descriptor._GetCtype(fields_copy[:last])
1061cb0ef41Sopenharmony_ci    else:
1071cb0ef41Sopenharmony_ci      complete_ctype = self.ctype
1081cb0ef41Sopenharmony_ci    return complete_ctype.from_buffer(memory, offset)
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  @staticmethod
1111cb0ef41Sopenharmony_ci  def _GetCtype(fields):
1121cb0ef41Sopenharmony_ci    class Raw(ctypes.Structure):
1131cb0ef41Sopenharmony_ci      _fields_ = fields
1141cb0ef41Sopenharmony_ci      _pack_ = 1
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci      def __str__(self):
1171cb0ef41Sopenharmony_ci        return "{" + ", ".join("%s: %s" % (field, self.__getattribute__(field))
1181cb0ef41Sopenharmony_ci                               for field, _ in Raw._fields_) + "}"
1191cb0ef41Sopenharmony_ci    return Raw
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cidef FullDump(reader, heap):
1231cb0ef41Sopenharmony_ci  """Dump all available memory regions."""
1241cb0ef41Sopenharmony_ci  def dump_region(reader, start, size, location):
1251cb0ef41Sopenharmony_ci    print()
1261cb0ef41Sopenharmony_ci    while start & 3 != 0:
1271cb0ef41Sopenharmony_ci      start += 1
1281cb0ef41Sopenharmony_ci      size -= 1
1291cb0ef41Sopenharmony_ci      location += 1
1301cb0ef41Sopenharmony_ci    is_executable = reader.IsProbableExecutableRegion(location, size)
1311cb0ef41Sopenharmony_ci    is_ascii = reader.IsProbableASCIIRegion(location, size)
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    if is_executable is not False:
1341cb0ef41Sopenharmony_ci      lines = reader.GetDisasmLines(start, size)
1351cb0ef41Sopenharmony_ci      for line in lines:
1361cb0ef41Sopenharmony_ci        print(FormatDisasmLine(start, heap, line))
1371cb0ef41Sopenharmony_ci      print()
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci    if is_ascii is not False:
1401cb0ef41Sopenharmony_ci      # Output in the same format as the Unix hd command
1411cb0ef41Sopenharmony_ci      addr = start
1421cb0ef41Sopenharmony_ci      for i in range(0, size, 16):
1431cb0ef41Sopenharmony_ci        slot = i + location
1441cb0ef41Sopenharmony_ci        hex_line = ""
1451cb0ef41Sopenharmony_ci        asc_line = ""
1461cb0ef41Sopenharmony_ci        for i in range(16):
1471cb0ef41Sopenharmony_ci          if slot + i < location + size:
1481cb0ef41Sopenharmony_ci            byte = ctypes.c_uint8.from_buffer(reader.minidump, slot + i).value
1491cb0ef41Sopenharmony_ci            if byte >= 0x20 and byte < 0x7f:
1501cb0ef41Sopenharmony_ci              asc_line += chr(byte)
1511cb0ef41Sopenharmony_ci            else:
1521cb0ef41Sopenharmony_ci              asc_line += "."
1531cb0ef41Sopenharmony_ci            hex_line += " %02x" % (byte)
1541cb0ef41Sopenharmony_ci          else:
1551cb0ef41Sopenharmony_ci            hex_line += "   "
1561cb0ef41Sopenharmony_ci          if i == 7:
1571cb0ef41Sopenharmony_ci            hex_line += " "
1581cb0ef41Sopenharmony_ci        print("%s  %s |%s|" % (reader.FormatIntPtr(addr),
1591cb0ef41Sopenharmony_ci                               hex_line,
1601cb0ef41Sopenharmony_ci                               asc_line))
1611cb0ef41Sopenharmony_ci        addr += 16
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci    if is_executable is not True and is_ascii is not True:
1641cb0ef41Sopenharmony_ci      print("%s - %s" % (reader.FormatIntPtr(start),
1651cb0ef41Sopenharmony_ci                         reader.FormatIntPtr(start + size)))
1661cb0ef41Sopenharmony_ci      print(start + size + 1);
1671cb0ef41Sopenharmony_ci      for i in range(0, size, reader.MachinePointerSize()):
1681cb0ef41Sopenharmony_ci        slot = start + i
1691cb0ef41Sopenharmony_ci        maybe_address = reader.ReadUIntPtr(slot)
1701cb0ef41Sopenharmony_ci        heap_object = heap.FindObject(maybe_address)
1711cb0ef41Sopenharmony_ci        print("%s: %s" % (reader.FormatIntPtr(slot),
1721cb0ef41Sopenharmony_ci                          reader.FormatIntPtr(maybe_address)))
1731cb0ef41Sopenharmony_ci        if heap_object:
1741cb0ef41Sopenharmony_ci          heap_object.Print(Printer())
1751cb0ef41Sopenharmony_ci          print()
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  reader.ForEachMemoryRegion(dump_region)
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci# Heap constants generated by 'make grokdump' in v8heapconst module.
1801cb0ef41Sopenharmony_ciINSTANCE_TYPES = v8heapconst.INSTANCE_TYPES
1811cb0ef41Sopenharmony_ciKNOWN_MAPS = v8heapconst.KNOWN_MAPS
1821cb0ef41Sopenharmony_ciKNOWN_OBJECTS = v8heapconst.KNOWN_OBJECTS
1831cb0ef41Sopenharmony_ciFRAME_MARKERS = v8heapconst.FRAME_MARKERS
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci# Markers pushed on the stack by PushStackTraceAndDie
1861cb0ef41Sopenharmony_ciMAGIC_MARKER_PAIRS = (
1871cb0ef41Sopenharmony_ci    (0xbbbbbbbb, 0xbbbbbbbb),
1881cb0ef41Sopenharmony_ci    (0xfefefefe, 0xfefefeff),
1891cb0ef41Sopenharmony_ci)
1901cb0ef41Sopenharmony_ci# See StackTraceFailureMessage in isolate.h
1911cb0ef41Sopenharmony_ciSTACK_TRACE_MARKER = 0xdecade30
1921cb0ef41Sopenharmony_ci# See FailureMessage in logging.cc
1931cb0ef41Sopenharmony_ciERROR_MESSAGE_MARKER = 0xdecade10
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci# Set of structures and constants that describe the layout of minidump
1961cb0ef41Sopenharmony_ci# files. Based on MSDN and Google Breakpad.
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ciMINIDUMP_HEADER = Descriptor([
1991cb0ef41Sopenharmony_ci  ("signature", ctypes.c_uint32),
2001cb0ef41Sopenharmony_ci  ("version", ctypes.c_uint32),
2011cb0ef41Sopenharmony_ci  ("stream_count", ctypes.c_uint32),
2021cb0ef41Sopenharmony_ci  ("stream_directories_rva", ctypes.c_uint32),
2031cb0ef41Sopenharmony_ci  ("checksum", ctypes.c_uint32),
2041cb0ef41Sopenharmony_ci  ("time_date_stampt", ctypes.c_uint32),
2051cb0ef41Sopenharmony_ci  ("flags", ctypes.c_uint64)
2061cb0ef41Sopenharmony_ci])
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ciMINIDUMP_LOCATION_DESCRIPTOR = Descriptor([
2091cb0ef41Sopenharmony_ci  ("data_size", ctypes.c_uint32),
2101cb0ef41Sopenharmony_ci  ("rva", ctypes.c_uint32)
2111cb0ef41Sopenharmony_ci])
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ciMINIDUMP_STRING = Descriptor([
2141cb0ef41Sopenharmony_ci  ("length", ctypes.c_uint32),
2151cb0ef41Sopenharmony_ci  ("buffer", lambda t: ctypes.c_uint8 * (t.length + 2))
2161cb0ef41Sopenharmony_ci])
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ciMINIDUMP_DIRECTORY = Descriptor([
2191cb0ef41Sopenharmony_ci  ("stream_type", ctypes.c_uint32),
2201cb0ef41Sopenharmony_ci  ("location", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
2211cb0ef41Sopenharmony_ci])
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ciMD_EXCEPTION_MAXIMUM_PARAMETERS = 15
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ciMINIDUMP_EXCEPTION = Descriptor([
2261cb0ef41Sopenharmony_ci  ("code", ctypes.c_uint32),
2271cb0ef41Sopenharmony_ci  ("flags", ctypes.c_uint32),
2281cb0ef41Sopenharmony_ci  ("record", ctypes.c_uint64),
2291cb0ef41Sopenharmony_ci  ("address", ctypes.c_uint64),
2301cb0ef41Sopenharmony_ci  ("parameter_count", ctypes.c_uint32),
2311cb0ef41Sopenharmony_ci  ("unused_alignment", ctypes.c_uint32),
2321cb0ef41Sopenharmony_ci  ("information", ctypes.c_uint64 * MD_EXCEPTION_MAXIMUM_PARAMETERS)
2331cb0ef41Sopenharmony_ci])
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ciMINIDUMP_EXCEPTION_STREAM = Descriptor([
2361cb0ef41Sopenharmony_ci  ("thread_id", ctypes.c_uint32),
2371cb0ef41Sopenharmony_ci  ("unused_alignment", ctypes.c_uint32),
2381cb0ef41Sopenharmony_ci  ("exception", MINIDUMP_EXCEPTION.ctype),
2391cb0ef41Sopenharmony_ci  ("thread_context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
2401cb0ef41Sopenharmony_ci])
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci# Stream types.
2431cb0ef41Sopenharmony_ciMD_UNUSED_STREAM = 0
2441cb0ef41Sopenharmony_ciMD_RESERVED_STREAM_0 = 1
2451cb0ef41Sopenharmony_ciMD_RESERVED_STREAM_1 = 2
2461cb0ef41Sopenharmony_ciMD_THREAD_LIST_STREAM = 3
2471cb0ef41Sopenharmony_ciMD_MODULE_LIST_STREAM = 4
2481cb0ef41Sopenharmony_ciMD_MEMORY_LIST_STREAM = 5
2491cb0ef41Sopenharmony_ciMD_EXCEPTION_STREAM = 6
2501cb0ef41Sopenharmony_ciMD_SYSTEM_INFO_STREAM = 7
2511cb0ef41Sopenharmony_ciMD_THREAD_EX_LIST_STREAM = 8
2521cb0ef41Sopenharmony_ciMD_MEMORY_64_LIST_STREAM = 9
2531cb0ef41Sopenharmony_ciMD_COMMENT_STREAM_A = 10
2541cb0ef41Sopenharmony_ciMD_COMMENT_STREAM_W = 11
2551cb0ef41Sopenharmony_ciMD_HANDLE_DATA_STREAM = 12
2561cb0ef41Sopenharmony_ciMD_FUNCTION_TABLE_STREAM = 13
2571cb0ef41Sopenharmony_ciMD_UNLOADED_MODULE_LIST_STREAM = 14
2581cb0ef41Sopenharmony_ciMD_MISC_INFO_STREAM = 15
2591cb0ef41Sopenharmony_ciMD_MEMORY_INFO_LIST_STREAM = 16
2601cb0ef41Sopenharmony_ciMD_THREAD_INFO_LIST_STREAM = 17
2611cb0ef41Sopenharmony_ciMD_HANDLE_OPERATION_LIST_STREAM = 18
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ciMD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE = 80
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ciMINIDUMP_FLOATING_SAVE_AREA_X86 = Descriptor([
2661cb0ef41Sopenharmony_ci  ("control_word", ctypes.c_uint32),
2671cb0ef41Sopenharmony_ci  ("status_word", ctypes.c_uint32),
2681cb0ef41Sopenharmony_ci  ("tag_word", ctypes.c_uint32),
2691cb0ef41Sopenharmony_ci  ("error_offset", ctypes.c_uint32),
2701cb0ef41Sopenharmony_ci  ("error_selector", ctypes.c_uint32),
2711cb0ef41Sopenharmony_ci  ("data_offset", ctypes.c_uint32),
2721cb0ef41Sopenharmony_ci  ("data_selector", ctypes.c_uint32),
2731cb0ef41Sopenharmony_ci  ("register_area", ctypes.c_uint8 * MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE),
2741cb0ef41Sopenharmony_ci  ("cr0_npx_state", ctypes.c_uint32)
2751cb0ef41Sopenharmony_ci])
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ciMD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE = 512
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci# Context flags.
2801cb0ef41Sopenharmony_ciMD_CONTEXT_X86 = 0x00010000
2811cb0ef41Sopenharmony_ciMD_CONTEXT_X86_CONTROL = (MD_CONTEXT_X86 | 0x00000001)
2821cb0ef41Sopenharmony_ciMD_CONTEXT_X86_INTEGER = (MD_CONTEXT_X86 | 0x00000002)
2831cb0ef41Sopenharmony_ciMD_CONTEXT_X86_SEGMENTS = (MD_CONTEXT_X86 | 0x00000004)
2841cb0ef41Sopenharmony_ciMD_CONTEXT_X86_FLOATING_POINT = (MD_CONTEXT_X86 | 0x00000008)
2851cb0ef41Sopenharmony_ciMD_CONTEXT_X86_DEBUG_REGISTERS = (MD_CONTEXT_X86 | 0x00000010)
2861cb0ef41Sopenharmony_ciMD_CONTEXT_X86_EXTENDED_REGISTERS = (MD_CONTEXT_X86 | 0x00000020)
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_cidef EnableOnFlag(type, flag):
2891cb0ef41Sopenharmony_ci  return lambda o: [None, type][int((o.context_flags & flag) != 0)]
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ciMINIDUMP_CONTEXT_X86 = Descriptor([
2921cb0ef41Sopenharmony_ci  ("context_flags", ctypes.c_uint32),
2931cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_DEBUG_REGISTERS.
2941cb0ef41Sopenharmony_ci  ("dr0", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
2951cb0ef41Sopenharmony_ci  ("dr1", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
2961cb0ef41Sopenharmony_ci  ("dr2", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
2971cb0ef41Sopenharmony_ci  ("dr3", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
2981cb0ef41Sopenharmony_ci  ("dr6", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
2991cb0ef41Sopenharmony_ci  ("dr7", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_DEBUG_REGISTERS)),
3001cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_FLOATING_POINT.
3011cb0ef41Sopenharmony_ci  ("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_X86.ctype,
3021cb0ef41Sopenharmony_ci                              MD_CONTEXT_X86_FLOATING_POINT)),
3031cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_SEGMENTS.
3041cb0ef41Sopenharmony_ci  ("gs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
3051cb0ef41Sopenharmony_ci  ("fs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
3061cb0ef41Sopenharmony_ci  ("es", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
3071cb0ef41Sopenharmony_ci  ("ds", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_SEGMENTS)),
3081cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_INTEGER.
3091cb0ef41Sopenharmony_ci  ("edi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3101cb0ef41Sopenharmony_ci  ("esi", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3111cb0ef41Sopenharmony_ci  ("ebx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3121cb0ef41Sopenharmony_ci  ("edx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3131cb0ef41Sopenharmony_ci  ("ecx", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3141cb0ef41Sopenharmony_ci  ("eax", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_INTEGER)),
3151cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_CONTROL.
3161cb0ef41Sopenharmony_ci  ("ebp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3171cb0ef41Sopenharmony_ci  ("eip", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3181cb0ef41Sopenharmony_ci  ("cs", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3191cb0ef41Sopenharmony_ci  ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3201cb0ef41Sopenharmony_ci  ("esp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3211cb0ef41Sopenharmony_ci  ("ss", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_X86_CONTROL)),
3221cb0ef41Sopenharmony_ci  # MD_CONTEXT_X86_EXTENDED_REGISTERS.
3231cb0ef41Sopenharmony_ci  ("extended_registers",
3241cb0ef41Sopenharmony_ci   EnableOnFlag(ctypes.c_uint8 * MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE,
3251cb0ef41Sopenharmony_ci                MD_CONTEXT_X86_EXTENDED_REGISTERS))
3261cb0ef41Sopenharmony_ci])
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ciMD_CONTEXT_ARM = 0x40000000
3291cb0ef41Sopenharmony_ciMD_CONTEXT_ARM_INTEGER = (MD_CONTEXT_ARM | 0x00000002)
3301cb0ef41Sopenharmony_ciMD_CONTEXT_ARM_FLOATING_POINT = (MD_CONTEXT_ARM | 0x00000004)
3311cb0ef41Sopenharmony_ciMD_FLOATINGSAVEAREA_ARM_FPR_COUNT = 32
3321cb0ef41Sopenharmony_ciMD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT = 8
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ciMINIDUMP_FLOATING_SAVE_AREA_ARM = Descriptor([
3351cb0ef41Sopenharmony_ci  ("fpscr", ctypes.c_uint64),
3361cb0ef41Sopenharmony_ci  ("regs", ctypes.c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPR_COUNT),
3371cb0ef41Sopenharmony_ci  ("extra", ctypes.c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT)
3381cb0ef41Sopenharmony_ci])
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ciMINIDUMP_CONTEXT_ARM = Descriptor([
3411cb0ef41Sopenharmony_ci  ("context_flags", ctypes.c_uint32),
3421cb0ef41Sopenharmony_ci  # MD_CONTEXT_ARM_INTEGER.
3431cb0ef41Sopenharmony_ci  ("r0", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3441cb0ef41Sopenharmony_ci  ("r1", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3451cb0ef41Sopenharmony_ci  ("r2", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3461cb0ef41Sopenharmony_ci  ("r3", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3471cb0ef41Sopenharmony_ci  ("r4", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3481cb0ef41Sopenharmony_ci  ("r5", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3491cb0ef41Sopenharmony_ci  ("r6", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3501cb0ef41Sopenharmony_ci  ("r7", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3511cb0ef41Sopenharmony_ci  ("r8", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3521cb0ef41Sopenharmony_ci  ("r9", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3531cb0ef41Sopenharmony_ci  ("r10", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3541cb0ef41Sopenharmony_ci  ("r11", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3551cb0ef41Sopenharmony_ci  ("r12", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3561cb0ef41Sopenharmony_ci  ("sp", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3571cb0ef41Sopenharmony_ci  ("lr", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3581cb0ef41Sopenharmony_ci  ("pc", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_ARM_INTEGER)),
3591cb0ef41Sopenharmony_ci  ("cpsr", ctypes.c_uint32),
3601cb0ef41Sopenharmony_ci  ("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_ARM.ctype,
3611cb0ef41Sopenharmony_ci                              MD_CONTEXT_ARM_FLOATING_POINT))
3621cb0ef41Sopenharmony_ci])
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ciMD_CONTEXT_ARM64 =  0x80000000
3661cb0ef41Sopenharmony_ciMD_CONTEXT_ARM64_INTEGER = (MD_CONTEXT_ARM64 | 0x00000002)
3671cb0ef41Sopenharmony_ciMD_CONTEXT_ARM64_FLOATING_POINT = (MD_CONTEXT_ARM64 | 0x00000004)
3681cb0ef41Sopenharmony_ciMD_FLOATINGSAVEAREA_ARM64_FPR_COUNT = 64
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ciMINIDUMP_FLOATING_SAVE_AREA_ARM = Descriptor([
3711cb0ef41Sopenharmony_ci  ("fpscr", ctypes.c_uint64),
3721cb0ef41Sopenharmony_ci  ("regs", ctypes.c_uint64 * MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT),
3731cb0ef41Sopenharmony_ci])
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ciMINIDUMP_CONTEXT_ARM64 = Descriptor([
3761cb0ef41Sopenharmony_ci  ("context_flags", ctypes.c_uint64),
3771cb0ef41Sopenharmony_ci  # MD_CONTEXT_ARM64_INTEGER.
3781cb0ef41Sopenharmony_ci  ("r0", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3791cb0ef41Sopenharmony_ci  ("r1", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3801cb0ef41Sopenharmony_ci  ("r2", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3811cb0ef41Sopenharmony_ci  ("r3", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3821cb0ef41Sopenharmony_ci  ("r4", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3831cb0ef41Sopenharmony_ci  ("r5", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3841cb0ef41Sopenharmony_ci  ("r6", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3851cb0ef41Sopenharmony_ci  ("r7", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3861cb0ef41Sopenharmony_ci  ("r8", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3871cb0ef41Sopenharmony_ci  ("r9", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3881cb0ef41Sopenharmony_ci  ("r10", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3891cb0ef41Sopenharmony_ci  ("r11", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3901cb0ef41Sopenharmony_ci  ("r12", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3911cb0ef41Sopenharmony_ci  ("r13", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3921cb0ef41Sopenharmony_ci  ("r14", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3931cb0ef41Sopenharmony_ci  ("r15", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3941cb0ef41Sopenharmony_ci  ("r16", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3951cb0ef41Sopenharmony_ci  ("r17", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3961cb0ef41Sopenharmony_ci  ("r18", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3971cb0ef41Sopenharmony_ci  ("r19", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3981cb0ef41Sopenharmony_ci  ("r20", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
3991cb0ef41Sopenharmony_ci  ("r21", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4001cb0ef41Sopenharmony_ci  ("r22", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4011cb0ef41Sopenharmony_ci  ("r23", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4021cb0ef41Sopenharmony_ci  ("r24", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4031cb0ef41Sopenharmony_ci  ("r25", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4041cb0ef41Sopenharmony_ci  ("r26", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4051cb0ef41Sopenharmony_ci  ("r27", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4061cb0ef41Sopenharmony_ci  ("r28", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4071cb0ef41Sopenharmony_ci  ("fp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4081cb0ef41Sopenharmony_ci  ("lr", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4091cb0ef41Sopenharmony_ci  ("sp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4101cb0ef41Sopenharmony_ci  ("pc", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_ARM64_INTEGER)),
4111cb0ef41Sopenharmony_ci  ("cpsr", ctypes.c_uint32),
4121cb0ef41Sopenharmony_ci  ("float_save", EnableOnFlag(MINIDUMP_FLOATING_SAVE_AREA_ARM.ctype,
4131cb0ef41Sopenharmony_ci                              MD_CONTEXT_ARM64_FLOATING_POINT))
4141cb0ef41Sopenharmony_ci])
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64 = 0x00100000
4181cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001)
4191cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002)
4201cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64_SEGMENTS = (MD_CONTEXT_AMD64 | 0x00000004)
4211cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64_FLOATING_POINT = (MD_CONTEXT_AMD64 | 0x00000008)
4221cb0ef41Sopenharmony_ciMD_CONTEXT_AMD64_DEBUG_REGISTERS = (MD_CONTEXT_AMD64 | 0x00000010)
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ciMINIDUMP_CONTEXT_AMD64 = Descriptor([
4251cb0ef41Sopenharmony_ci  ("p1_home", ctypes.c_uint64),
4261cb0ef41Sopenharmony_ci  ("p2_home", ctypes.c_uint64),
4271cb0ef41Sopenharmony_ci  ("p3_home", ctypes.c_uint64),
4281cb0ef41Sopenharmony_ci  ("p4_home", ctypes.c_uint64),
4291cb0ef41Sopenharmony_ci  ("p5_home", ctypes.c_uint64),
4301cb0ef41Sopenharmony_ci  ("p6_home", ctypes.c_uint64),
4311cb0ef41Sopenharmony_ci  ("context_flags", ctypes.c_uint32),
4321cb0ef41Sopenharmony_ci  ("mx_csr", ctypes.c_uint32),
4331cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_CONTROL.
4341cb0ef41Sopenharmony_ci  ("cs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)),
4351cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_SEGMENTS
4361cb0ef41Sopenharmony_ci  ("ds", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
4371cb0ef41Sopenharmony_ci  ("es", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
4381cb0ef41Sopenharmony_ci  ("fs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
4391cb0ef41Sopenharmony_ci  ("gs", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_SEGMENTS)),
4401cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_CONTROL.
4411cb0ef41Sopenharmony_ci  ("ss", EnableOnFlag(ctypes.c_uint16, MD_CONTEXT_AMD64_CONTROL)),
4421cb0ef41Sopenharmony_ci  ("eflags", EnableOnFlag(ctypes.c_uint32, MD_CONTEXT_AMD64_CONTROL)),
4431cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_DEBUG_REGISTERS.
4441cb0ef41Sopenharmony_ci  ("dr0", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4451cb0ef41Sopenharmony_ci  ("dr1", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4461cb0ef41Sopenharmony_ci  ("dr2", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4471cb0ef41Sopenharmony_ci  ("dr3", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4481cb0ef41Sopenharmony_ci  ("dr6", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4491cb0ef41Sopenharmony_ci  ("dr7", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4501cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_INTEGER.
4511cb0ef41Sopenharmony_ci  ("rax", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4521cb0ef41Sopenharmony_ci  ("rcx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4531cb0ef41Sopenharmony_ci  ("rdx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4541cb0ef41Sopenharmony_ci  ("rbx", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4551cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_CONTROL.
4561cb0ef41Sopenharmony_ci  ("rsp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)),
4571cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_INTEGER.
4581cb0ef41Sopenharmony_ci  ("rbp", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4591cb0ef41Sopenharmony_ci  ("rsi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4601cb0ef41Sopenharmony_ci  ("rdi", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4611cb0ef41Sopenharmony_ci  ("r8", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4621cb0ef41Sopenharmony_ci  ("r9", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4631cb0ef41Sopenharmony_ci  ("r10", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4641cb0ef41Sopenharmony_ci  ("r11", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4651cb0ef41Sopenharmony_ci  ("r12", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4661cb0ef41Sopenharmony_ci  ("r13", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4671cb0ef41Sopenharmony_ci  ("r14", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4681cb0ef41Sopenharmony_ci  ("r15", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_INTEGER)),
4691cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_CONTROL.
4701cb0ef41Sopenharmony_ci  ("rip", EnableOnFlag(ctypes.c_uint64, MD_CONTEXT_AMD64_CONTROL)),
4711cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_FLOATING_POINT
4721cb0ef41Sopenharmony_ci  ("sse_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26),
4731cb0ef41Sopenharmony_ci                                 MD_CONTEXT_AMD64_FLOATING_POINT)),
4741cb0ef41Sopenharmony_ci  ("vector_registers", EnableOnFlag(ctypes.c_uint8 * (16 * 26),
4751cb0ef41Sopenharmony_ci                                    MD_CONTEXT_AMD64_FLOATING_POINT)),
4761cb0ef41Sopenharmony_ci  ("vector_control", EnableOnFlag(ctypes.c_uint64,
4771cb0ef41Sopenharmony_ci                                  MD_CONTEXT_AMD64_FLOATING_POINT)),
4781cb0ef41Sopenharmony_ci  # MD_CONTEXT_AMD64_DEBUG_REGISTERS.
4791cb0ef41Sopenharmony_ci  ("debug_control", EnableOnFlag(ctypes.c_uint64,
4801cb0ef41Sopenharmony_ci                                 MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4811cb0ef41Sopenharmony_ci  ("last_branch_to_rip", EnableOnFlag(ctypes.c_uint64,
4821cb0ef41Sopenharmony_ci                                      MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4831cb0ef41Sopenharmony_ci  ("last_branch_from_rip", EnableOnFlag(ctypes.c_uint64,
4841cb0ef41Sopenharmony_ci                                        MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4851cb0ef41Sopenharmony_ci  ("last_exception_to_rip", EnableOnFlag(ctypes.c_uint64,
4861cb0ef41Sopenharmony_ci                                         MD_CONTEXT_AMD64_DEBUG_REGISTERS)),
4871cb0ef41Sopenharmony_ci  ("last_exception_from_rip", EnableOnFlag(ctypes.c_uint64,
4881cb0ef41Sopenharmony_ci                                           MD_CONTEXT_AMD64_DEBUG_REGISTERS))
4891cb0ef41Sopenharmony_ci])
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ciMINIDUMP_MEMORY_DESCRIPTOR = Descriptor([
4921cb0ef41Sopenharmony_ci  ("start", ctypes.c_uint64),
4931cb0ef41Sopenharmony_ci  ("memory", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
4941cb0ef41Sopenharmony_ci])
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ciMINIDUMP_MEMORY_DESCRIPTOR64 = Descriptor([
4971cb0ef41Sopenharmony_ci  ("start", ctypes.c_uint64),
4981cb0ef41Sopenharmony_ci  ("size", ctypes.c_uint64)
4991cb0ef41Sopenharmony_ci])
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ciMINIDUMP_MEMORY_LIST = Descriptor([
5021cb0ef41Sopenharmony_ci  ("range_count", ctypes.c_uint32),
5031cb0ef41Sopenharmony_ci  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR.ctype * m.range_count)
5041cb0ef41Sopenharmony_ci])
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ciMINIDUMP_MEMORY_LIST_Mac = Descriptor([
5071cb0ef41Sopenharmony_ci  ("range_count", ctypes.c_uint32),
5081cb0ef41Sopenharmony_ci  ("junk", ctypes.c_uint32),
5091cb0ef41Sopenharmony_ci  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR.ctype * m.range_count)
5101cb0ef41Sopenharmony_ci])
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ciMINIDUMP_MEMORY_LIST64 = Descriptor([
5131cb0ef41Sopenharmony_ci  ("range_count", ctypes.c_uint64),
5141cb0ef41Sopenharmony_ci  ("base_rva", ctypes.c_uint64),
5151cb0ef41Sopenharmony_ci  ("ranges", lambda m: MINIDUMP_MEMORY_DESCRIPTOR64.ctype * m.range_count)
5161cb0ef41Sopenharmony_ci])
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ciMINIDUMP_THREAD = Descriptor([
5191cb0ef41Sopenharmony_ci  ("id", ctypes.c_uint32),
5201cb0ef41Sopenharmony_ci  ("suspend_count", ctypes.c_uint32),
5211cb0ef41Sopenharmony_ci  ("priority_class", ctypes.c_uint32),
5221cb0ef41Sopenharmony_ci  ("priority", ctypes.c_uint32),
5231cb0ef41Sopenharmony_ci  ("ted", ctypes.c_uint64),
5241cb0ef41Sopenharmony_ci  ("stack", MINIDUMP_MEMORY_DESCRIPTOR.ctype),
5251cb0ef41Sopenharmony_ci  ("context", MINIDUMP_LOCATION_DESCRIPTOR.ctype)
5261cb0ef41Sopenharmony_ci])
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ciMINIDUMP_THREAD_LIST = Descriptor([
5291cb0ef41Sopenharmony_ci  ("thread_count", ctypes.c_uint32),
5301cb0ef41Sopenharmony_ci  ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
5311cb0ef41Sopenharmony_ci])
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ciMINIDUMP_THREAD_LIST_Mac = Descriptor([
5341cb0ef41Sopenharmony_ci  ("thread_count", ctypes.c_uint32),
5351cb0ef41Sopenharmony_ci  ("junk", ctypes.c_uint32),
5361cb0ef41Sopenharmony_ci  ("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
5371cb0ef41Sopenharmony_ci])
5381cb0ef41Sopenharmony_ci
5391cb0ef41Sopenharmony_ciMINIDUMP_VS_FIXEDFILEINFO = Descriptor([
5401cb0ef41Sopenharmony_ci  ("dwSignature", ctypes.c_uint32),
5411cb0ef41Sopenharmony_ci  ("dwStrucVersion", ctypes.c_uint32),
5421cb0ef41Sopenharmony_ci  ("dwFileVersionMS", ctypes.c_uint32),
5431cb0ef41Sopenharmony_ci  ("dwFileVersionLS", ctypes.c_uint32),
5441cb0ef41Sopenharmony_ci  ("dwProductVersionMS", ctypes.c_uint32),
5451cb0ef41Sopenharmony_ci  ("dwProductVersionLS", ctypes.c_uint32),
5461cb0ef41Sopenharmony_ci  ("dwFileFlagsMask", ctypes.c_uint32),
5471cb0ef41Sopenharmony_ci  ("dwFileFlags", ctypes.c_uint32),
5481cb0ef41Sopenharmony_ci  ("dwFileOS", ctypes.c_uint32),
5491cb0ef41Sopenharmony_ci  ("dwFileType", ctypes.c_uint32),
5501cb0ef41Sopenharmony_ci  ("dwFileSubtype", ctypes.c_uint32),
5511cb0ef41Sopenharmony_ci  ("dwFileDateMS", ctypes.c_uint32),
5521cb0ef41Sopenharmony_ci  ("dwFileDateLS", ctypes.c_uint32)
5531cb0ef41Sopenharmony_ci])
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ciMINIDUMP_RAW_MODULE = Descriptor([
5561cb0ef41Sopenharmony_ci  ("base_of_image", ctypes.c_uint64),
5571cb0ef41Sopenharmony_ci  ("size_of_image", ctypes.c_uint32),
5581cb0ef41Sopenharmony_ci  ("checksum", ctypes.c_uint32),
5591cb0ef41Sopenharmony_ci  ("time_date_stamp", ctypes.c_uint32),
5601cb0ef41Sopenharmony_ci  ("module_name_rva", ctypes.c_uint32),
5611cb0ef41Sopenharmony_ci  ("version_info", MINIDUMP_VS_FIXEDFILEINFO.ctype),
5621cb0ef41Sopenharmony_ci  ("cv_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
5631cb0ef41Sopenharmony_ci  ("misc_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
5641cb0ef41Sopenharmony_ci  ("reserved0", ctypes.c_uint32 * 2),
5651cb0ef41Sopenharmony_ci  ("reserved1", ctypes.c_uint32 * 2)
5661cb0ef41Sopenharmony_ci])
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ciMINIDUMP_MODULE_LIST = Descriptor([
5691cb0ef41Sopenharmony_ci  ("number_of_modules", ctypes.c_uint32),
5701cb0ef41Sopenharmony_ci  ("modules", lambda t: MINIDUMP_RAW_MODULE.ctype * t.number_of_modules)
5711cb0ef41Sopenharmony_ci])
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ciMINIDUMP_MODULE_LIST_Mac = Descriptor([
5741cb0ef41Sopenharmony_ci  ("number_of_modules", ctypes.c_uint32),
5751cb0ef41Sopenharmony_ci  ("junk", ctypes.c_uint32),
5761cb0ef41Sopenharmony_ci  ("modules", lambda t: MINIDUMP_RAW_MODULE.ctype * t.number_of_modules)
5771cb0ef41Sopenharmony_ci])
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ciMINIDUMP_RAW_SYSTEM_INFO = Descriptor([
5801cb0ef41Sopenharmony_ci  ("processor_architecture", ctypes.c_uint16)
5811cb0ef41Sopenharmony_ci])
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ciMD_CPU_ARCHITECTURE_X86 = 0
5841cb0ef41Sopenharmony_ciMD_CPU_ARCHITECTURE_ARM = 5
5851cb0ef41Sopenharmony_ci# Breakpad used a custom value of 0x8003 here; Crashpad uses the new
5861cb0ef41Sopenharmony_ci# standardized value 12.
5871cb0ef41Sopenharmony_ciMD_CPU_ARCHITECTURE_ARM64 = 12
5881cb0ef41Sopenharmony_ciMD_CPU_ARCHITECTURE_ARM64_BREAKPAD_LEGACY = 0x8003
5891cb0ef41Sopenharmony_ciMD_CPU_ARCHITECTURE_AMD64 = 9
5901cb0ef41Sopenharmony_ci
5911cb0ef41Sopenharmony_ciOBJDUMP_BIN = None
5921cb0ef41Sopenharmony_ciDEFAULT_OBJDUMP_BIN = '/usr/bin/objdump'
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ciclass FuncSymbol:
5951cb0ef41Sopenharmony_ci  def __init__(self, start, size, name):
5961cb0ef41Sopenharmony_ci    self.start = start
5971cb0ef41Sopenharmony_ci    self.end = self.start + size
5981cb0ef41Sopenharmony_ci    self.name = name
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  def __cmp__(self, other):
6011cb0ef41Sopenharmony_ci    if isinstance(other, FuncSymbol):
6021cb0ef41Sopenharmony_ci      return self.start - other.start
6031cb0ef41Sopenharmony_ci    return self.start - other
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  def Covers(self, addr):
6061cb0ef41Sopenharmony_ci    return (self.start <= addr) and (addr < self.end)
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ciclass MinidumpReader(object):
6101cb0ef41Sopenharmony_ci  """Minidump (.dmp) reader."""
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  _HEADER_MAGIC = 0x504d444d
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  def __init__(self, options, minidump_name):
6151cb0ef41Sopenharmony_ci    self._reset()
6161cb0ef41Sopenharmony_ci    self.minidump_name = minidump_name
6171cb0ef41Sopenharmony_ci    if sys.platform == 'win32':
6181cb0ef41Sopenharmony_ci      self.minidump_file = open(minidump_name, "a+")
6191cb0ef41Sopenharmony_ci      self.minidump = mmap.mmap(self.minidump_file.fileno(), 0)
6201cb0ef41Sopenharmony_ci    else:
6211cb0ef41Sopenharmony_ci      self.minidump_file = open(minidump_name, "r")
6221cb0ef41Sopenharmony_ci      self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, mmap.MAP_PRIVATE)
6231cb0ef41Sopenharmony_ci    self.header = MINIDUMP_HEADER.Read(self.minidump, 0)
6241cb0ef41Sopenharmony_ci    if self.header.signature != MinidumpReader._HEADER_MAGIC:
6251cb0ef41Sopenharmony_ci      print("Warning: Unsupported minidump header magic!", file=sys.stderr)
6261cb0ef41Sopenharmony_ci    DebugPrint(self.header)
6271cb0ef41Sopenharmony_ci    offset = self.header.stream_directories_rva
6281cb0ef41Sopenharmony_ci    directories = []
6291cb0ef41Sopenharmony_ci    for _ in range(self.header.stream_count):
6301cb0ef41Sopenharmony_ci      directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset))
6311cb0ef41Sopenharmony_ci      offset += MINIDUMP_DIRECTORY.size
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci    self.symdir = options.symdir
6341cb0ef41Sopenharmony_ci    self._ReadArchitecture(directories)
6351cb0ef41Sopenharmony_ci    self._ReadDirectories(directories)
6361cb0ef41Sopenharmony_ci    self._FindObjdump(options)
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  def _reset(self):
6391cb0ef41Sopenharmony_ci    self.header = None
6401cb0ef41Sopenharmony_ci    self.arch = None
6411cb0ef41Sopenharmony_ci    self.exception = None
6421cb0ef41Sopenharmony_ci    self.exception_context = None
6431cb0ef41Sopenharmony_ci    self.memory_list = None
6441cb0ef41Sopenharmony_ci    self.memory_list64 = None
6451cb0ef41Sopenharmony_ci    self.module_list = None
6461cb0ef41Sopenharmony_ci    self.thread_map = {}
6471cb0ef41Sopenharmony_ci
6481cb0ef41Sopenharmony_ci    self.modules_with_symbols = []
6491cb0ef41Sopenharmony_ci    self.symbols = []
6501cb0ef41Sopenharmony_ci
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci  def _ReadArchitecture(self, directories):
6531cb0ef41Sopenharmony_ci    # Find MDRawSystemInfo stream and determine arch.
6541cb0ef41Sopenharmony_ci    for d in directories:
6551cb0ef41Sopenharmony_ci      if d.stream_type == MD_SYSTEM_INFO_STREAM:
6561cb0ef41Sopenharmony_ci        system_info = MINIDUMP_RAW_SYSTEM_INFO.Read(
6571cb0ef41Sopenharmony_ci            self.minidump, d.location.rva)
6581cb0ef41Sopenharmony_ci        self.arch = system_info.processor_architecture
6591cb0ef41Sopenharmony_ci        if self.arch == MD_CPU_ARCHITECTURE_ARM64_BREAKPAD_LEGACY:
6601cb0ef41Sopenharmony_ci          self.arch = MD_CPU_ARCHITECTURE_ARM64
6611cb0ef41Sopenharmony_ci        assert self.arch in [MD_CPU_ARCHITECTURE_AMD64,
6621cb0ef41Sopenharmony_ci                             MD_CPU_ARCHITECTURE_ARM,
6631cb0ef41Sopenharmony_ci                             MD_CPU_ARCHITECTURE_ARM64,
6641cb0ef41Sopenharmony_ci                             MD_CPU_ARCHITECTURE_X86]
6651cb0ef41Sopenharmony_ci    assert not self.arch is None
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci  def _ReadDirectories(self, directories):
6681cb0ef41Sopenharmony_ci    for d in directories:
6691cb0ef41Sopenharmony_ci      DebugPrint(d)
6701cb0ef41Sopenharmony_ci      if d.stream_type == MD_EXCEPTION_STREAM:
6711cb0ef41Sopenharmony_ci        self.exception = MINIDUMP_EXCEPTION_STREAM.Read(
6721cb0ef41Sopenharmony_ci          self.minidump, d.location.rva)
6731cb0ef41Sopenharmony_ci        DebugPrint(self.exception)
6741cb0ef41Sopenharmony_ci        self.exception_context = self.ContextDescriptor().Read(
6751cb0ef41Sopenharmony_ci            self.minidump, self.exception.thread_context.rva)
6761cb0ef41Sopenharmony_ci        DebugPrint(self.exception_context)
6771cb0ef41Sopenharmony_ci      elif d.stream_type == MD_THREAD_LIST_STREAM:
6781cb0ef41Sopenharmony_ci        thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva)
6791cb0ef41Sopenharmony_ci        if ctypes.sizeof(thread_list) + 4 == d.location.data_size:
6801cb0ef41Sopenharmony_ci          thread_list = MINIDUMP_THREAD_LIST_Mac.Read(
6811cb0ef41Sopenharmony_ci              self.minidump, d.location.rva)
6821cb0ef41Sopenharmony_ci        assert ctypes.sizeof(thread_list) == d.location.data_size
6831cb0ef41Sopenharmony_ci        DebugPrint(thread_list)
6841cb0ef41Sopenharmony_ci        for thread in thread_list.threads:
6851cb0ef41Sopenharmony_ci          DebugPrint(thread)
6861cb0ef41Sopenharmony_ci          self.thread_map[thread.id] = thread
6871cb0ef41Sopenharmony_ci      elif d.stream_type == MD_MODULE_LIST_STREAM:
6881cb0ef41Sopenharmony_ci        assert self.module_list is None
6891cb0ef41Sopenharmony_ci        self.module_list = MINIDUMP_MODULE_LIST.Read(
6901cb0ef41Sopenharmony_ci          self.minidump, d.location.rva)
6911cb0ef41Sopenharmony_ci        if ctypes.sizeof(self.module_list) + 4 == d.location.data_size:
6921cb0ef41Sopenharmony_ci          self.module_list = MINIDUMP_MODULE_LIST_Mac.Read(
6931cb0ef41Sopenharmony_ci              self.minidump, d.location.rva)
6941cb0ef41Sopenharmony_ci        assert ctypes.sizeof(self.module_list) == d.location.data_size
6951cb0ef41Sopenharmony_ci        DebugPrint(self.module_list)
6961cb0ef41Sopenharmony_ci      elif d.stream_type == MD_MEMORY_LIST_STREAM:
6971cb0ef41Sopenharmony_ci        print("Warning: This is not a full minidump!", file=sys.stderr)
6981cb0ef41Sopenharmony_ci        assert self.memory_list is None
6991cb0ef41Sopenharmony_ci        self.memory_list = MINIDUMP_MEMORY_LIST.Read(
7001cb0ef41Sopenharmony_ci          self.minidump, d.location.rva)
7011cb0ef41Sopenharmony_ci        if ctypes.sizeof(self.memory_list) + 4 == d.location.data_size:
7021cb0ef41Sopenharmony_ci          self.memory_list = MINIDUMP_MEMORY_LIST_Mac.Read(
7031cb0ef41Sopenharmony_ci              self.minidump, d.location.rva)
7041cb0ef41Sopenharmony_ci        assert ctypes.sizeof(self.memory_list) == d.location.data_size
7051cb0ef41Sopenharmony_ci        DebugPrint(self.memory_list)
7061cb0ef41Sopenharmony_ci      elif d.stream_type == MD_MEMORY_64_LIST_STREAM:
7071cb0ef41Sopenharmony_ci        assert self.memory_list64 is None
7081cb0ef41Sopenharmony_ci        self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read(
7091cb0ef41Sopenharmony_ci          self.minidump, d.location.rva)
7101cb0ef41Sopenharmony_ci        assert ctypes.sizeof(self.memory_list64) == d.location.data_size
7111cb0ef41Sopenharmony_ci        DebugPrint(self.memory_list64)
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci  def _FindObjdump(self, options):
7141cb0ef41Sopenharmony_ci    if options.objdump:
7151cb0ef41Sopenharmony_ci      objdump_bin = options.objdump
7161cb0ef41Sopenharmony_ci    else:
7171cb0ef41Sopenharmony_ci      objdump_bin = self._FindThirdPartyObjdump()
7181cb0ef41Sopenharmony_ci    if not objdump_bin or not os.path.exists(objdump_bin):
7191cb0ef41Sopenharmony_ci      print("# Cannot find '%s', falling back to default objdump '%s'" % (
7201cb0ef41Sopenharmony_ci          objdump_bin, DEFAULT_OBJDUMP_BIN))
7211cb0ef41Sopenharmony_ci      objdump_bin  = DEFAULT_OBJDUMP_BIN
7221cb0ef41Sopenharmony_ci    global OBJDUMP_BIN
7231cb0ef41Sopenharmony_ci    OBJDUMP_BIN = objdump_bin
7241cb0ef41Sopenharmony_ci    disasm.OBJDUMP_BIN = objdump_bin
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_ci  def _FindThirdPartyObjdump(self):
7271cb0ef41Sopenharmony_ci    # Try to find the platform specific objdump
7281cb0ef41Sopenharmony_ci    third_party_dir = os.path.join(
7291cb0ef41Sopenharmony_ci        os.path.dirname(os.path.dirname(__file__)), 'third_party')
7301cb0ef41Sopenharmony_ci    objdumps = []
7311cb0ef41Sopenharmony_ci    for root, dirs, files in os.walk(third_party_dir):
7321cb0ef41Sopenharmony_ci      for file in files:
7331cb0ef41Sopenharmony_ci        if file.endswith("objdump"):
7341cb0ef41Sopenharmony_ci          objdumps.append(os.path.join(root, file))
7351cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_ARM:
7361cb0ef41Sopenharmony_ci      platform_filter = 'arm-linux'
7371cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
7381cb0ef41Sopenharmony_ci      platform_filter = 'aarch64'
7391cb0ef41Sopenharmony_ci    else:
7401cb0ef41Sopenharmony_ci      # use default otherwise
7411cb0ef41Sopenharmony_ci      return None
7421cb0ef41Sopenharmony_ci    print(("# Looking for platform specific (%s) objdump in "
7431cb0ef41Sopenharmony_ci           "third_party directory.") % platform_filter)
7441cb0ef41Sopenharmony_ci    objdumps = list(filter(lambda file: platform_filter in file >= 0, objdumps))
7451cb0ef41Sopenharmony_ci    if len(objdumps) == 0:
7461cb0ef41Sopenharmony_ci      print("# Could not find platform specific objdump in third_party.")
7471cb0ef41Sopenharmony_ci      print("# Make sure you installed the correct SDK.")
7481cb0ef41Sopenharmony_ci      return None
7491cb0ef41Sopenharmony_ci    return objdumps[0]
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  def ContextDescriptor(self):
7521cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_X86:
7531cb0ef41Sopenharmony_ci      return MINIDUMP_CONTEXT_X86
7541cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
7551cb0ef41Sopenharmony_ci      return MINIDUMP_CONTEXT_AMD64
7561cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM:
7571cb0ef41Sopenharmony_ci      return MINIDUMP_CONTEXT_ARM
7581cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
7591cb0ef41Sopenharmony_ci      return MINIDUMP_CONTEXT_ARM64
7601cb0ef41Sopenharmony_ci    else:
7611cb0ef41Sopenharmony_ci      return None
7621cb0ef41Sopenharmony_ci
7631cb0ef41Sopenharmony_ci  def IsValidAlignedAddress(self, address):
7641cb0ef41Sopenharmony_ci    return self.IsAlignedAddress(address) and self.IsValidAddress(address)
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci  def IsValidAddress(self, address):
7671cb0ef41Sopenharmony_ci    return self.FindLocation(address) is not None
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci  def IsAlignedAddress(self, address):
7701cb0ef41Sopenharmony_ci    return (address % self.MachinePointerSize()) == 0
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci  def IsExceptionStackAddress(self, address):
7731cb0ef41Sopenharmony_ci    if not self.IsAlignedAddress(address): return False
7741cb0ef41Sopenharmony_ci    return self.IsAnyExceptionStackAddress(address)
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  def IsAnyExceptionStackAddress(self, address):
7771cb0ef41Sopenharmony_ci    return self.StackTop() <= address <= self.StackBottom()
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci  def IsValidExceptionStackAddress(self, address):
7801cb0ef41Sopenharmony_ci    if not self.IsValidAddress(address): return False
7811cb0ef41Sopenharmony_ci    return self.IsExceptionStackAddress(address)
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci  def IsModuleAddress(self, address):
7841cb0ef41Sopenharmony_ci    return self.GetModuleForAddress(address) != None
7851cb0ef41Sopenharmony_ci
7861cb0ef41Sopenharmony_ci  def GetModuleForAddress(self, address):
7871cb0ef41Sopenharmony_ci    for module in self.module_list.modules:
7881cb0ef41Sopenharmony_ci      start = module.base_of_image
7891cb0ef41Sopenharmony_ci      end = start + module.size_of_image
7901cb0ef41Sopenharmony_ci      if start <= address < end: return module
7911cb0ef41Sopenharmony_ci    return None
7921cb0ef41Sopenharmony_ci
7931cb0ef41Sopenharmony_ci  def ReadU8(self, address):
7941cb0ef41Sopenharmony_ci    location = self.FindLocation(address)
7951cb0ef41Sopenharmony_ci    return ctypes.c_uint8.from_buffer(self.minidump, location).value
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_ci  def ReadU32(self, address):
7981cb0ef41Sopenharmony_ci    location = self.FindLocation(address)
7991cb0ef41Sopenharmony_ci    return ctypes.c_uint32.from_buffer(self.minidump, location).value
8001cb0ef41Sopenharmony_ci
8011cb0ef41Sopenharmony_ci  def ReadU64(self, address):
8021cb0ef41Sopenharmony_ci    location = self.FindLocation(address)
8031cb0ef41Sopenharmony_ci    return ctypes.c_uint64.from_buffer(self.minidump, location).value
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  def Is64(self):
8061cb0ef41Sopenharmony_ci    return (self.arch == MD_CPU_ARCHITECTURE_ARM64 or
8071cb0ef41Sopenharmony_ci            self.arch == MD_CPU_ARCHITECTURE_AMD64)
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ci  def IsPointerCompressed(self):
8101cb0ef41Sopenharmony_ci    # Assume all 64-bit builds are pointer compressed.
8111cb0ef41Sopenharmony_ci    return self.Is64()
8121cb0ef41Sopenharmony_ci
8131cb0ef41Sopenharmony_ci  def Is32BitTagged(self):
8141cb0ef41Sopenharmony_ci    return not self.Is64() or self.IsPointerCompressed()
8151cb0ef41Sopenharmony_ci
8161cb0ef41Sopenharmony_ci  def ReadTagged(self, address):
8171cb0ef41Sopenharmony_ci    if self.Is32BitTagged():
8181cb0ef41Sopenharmony_ci      return self.ReadU32(address)
8191cb0ef41Sopenharmony_ci    return self.ReadU64(address)
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci  def ReadUIntPtr(self, address):
8221cb0ef41Sopenharmony_ci    if self.Is64():
8231cb0ef41Sopenharmony_ci      return self.ReadU64(address)
8241cb0ef41Sopenharmony_ci    return self.ReadU32(address)
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci  def ReadSized(self, address, size):
8271cb0ef41Sopenharmony_ci    if size == 8:
8281cb0ef41Sopenharmony_ci      return self.ReadU64(address)
8291cb0ef41Sopenharmony_ci    assert (size == 4)
8301cb0ef41Sopenharmony_ci    return self.ReadU32(address)
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci  def ReadBytes(self, address, size):
8331cb0ef41Sopenharmony_ci    location = self.FindLocation(address)
8341cb0ef41Sopenharmony_ci    return self.minidump[location:location + size]
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci  def _ReadWord(self, location):
8371cb0ef41Sopenharmony_ci    if self.Is64():
8381cb0ef41Sopenharmony_ci      return ctypes.c_uint64.from_buffer(self.minidump, location).value
8391cb0ef41Sopenharmony_ci    return ctypes.c_uint32.from_buffer(self.minidump, location).value
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci  def ReadAsciiPtr(self, address):
8421cb0ef41Sopenharmony_ci    ascii_content = [
8431cb0ef41Sopenharmony_ci        chr(c) if c >= 0x20 and c < 0x7f else '.'
8441cb0ef41Sopenharmony_ci        for c in self.ReadBytes(address, self.MachinePointerSize())
8451cb0ef41Sopenharmony_ci    ]
8461cb0ef41Sopenharmony_ci    return ''.join(ascii_content)
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_ci  def ReadAsciiString(self, address):
8491cb0ef41Sopenharmony_ci    string = ""
8501cb0ef41Sopenharmony_ci    while self.IsValidAddress(address):
8511cb0ef41Sopenharmony_ci      code = self.ReadU8(address)
8521cb0ef41Sopenharmony_ci      if 0 < code < 128:
8531cb0ef41Sopenharmony_ci        string += chr(code)
8541cb0ef41Sopenharmony_ci      else:
8551cb0ef41Sopenharmony_ci        break
8561cb0ef41Sopenharmony_ci      address += 1
8571cb0ef41Sopenharmony_ci    return string
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci  def IsProbableASCIIRegion(self, location, length):
8601cb0ef41Sopenharmony_ci    ascii_bytes = 0
8611cb0ef41Sopenharmony_ci    non_ascii_bytes = 0
8621cb0ef41Sopenharmony_ci    for i in range(length):
8631cb0ef41Sopenharmony_ci      loc = location + i
8641cb0ef41Sopenharmony_ci      byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
8651cb0ef41Sopenharmony_ci      if byte >= 0x7f:
8661cb0ef41Sopenharmony_ci        non_ascii_bytes += 1
8671cb0ef41Sopenharmony_ci      if byte < 0x20 and byte != 0:
8681cb0ef41Sopenharmony_ci        non_ascii_bytes += 1
8691cb0ef41Sopenharmony_ci      if byte < 0x7f and byte >= 0x20:
8701cb0ef41Sopenharmony_ci        ascii_bytes += 1
8711cb0ef41Sopenharmony_ci      if byte == 0xa:  # newline
8721cb0ef41Sopenharmony_ci        ascii_bytes += 1
8731cb0ef41Sopenharmony_ci    if ascii_bytes * 10 <= length:
8741cb0ef41Sopenharmony_ci      return False
8751cb0ef41Sopenharmony_ci    if length > 0 and ascii_bytes > non_ascii_bytes * 7:
8761cb0ef41Sopenharmony_ci      return True
8771cb0ef41Sopenharmony_ci    if ascii_bytes > non_ascii_bytes * 3:
8781cb0ef41Sopenharmony_ci      return None  # Maybe
8791cb0ef41Sopenharmony_ci    return False
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ci  def IsProbableExecutableRegion(self, location, length):
8821cb0ef41Sopenharmony_ci    opcode_bytes = 0
8831cb0ef41Sopenharmony_ci    sixty_four = self.Is64()
8841cb0ef41Sopenharmony_ci    for i in range(length):
8851cb0ef41Sopenharmony_ci      loc = location + i
8861cb0ef41Sopenharmony_ci      byte = ctypes.c_uint8.from_buffer(self.minidump, loc).value
8871cb0ef41Sopenharmony_ci      if (byte == 0x8b or           # mov
8881cb0ef41Sopenharmony_ci          byte == 0x89 or           # mov reg-reg
8891cb0ef41Sopenharmony_ci          (byte & 0xf0) == 0x50 or  # push/pop
8901cb0ef41Sopenharmony_ci          (sixty_four and (byte & 0xf0) == 0x40) or  # rex prefix
8911cb0ef41Sopenharmony_ci          byte == 0xc3 or           # return
8921cb0ef41Sopenharmony_ci          byte == 0x74 or           # jeq
8931cb0ef41Sopenharmony_ci          byte == 0x84 or           # jeq far
8941cb0ef41Sopenharmony_ci          byte == 0x75 or           # jne
8951cb0ef41Sopenharmony_ci          byte == 0x85 or           # jne far
8961cb0ef41Sopenharmony_ci          byte == 0xe8 or           # call
8971cb0ef41Sopenharmony_ci          byte == 0xe9 or           # jmp far
8981cb0ef41Sopenharmony_ci          byte == 0xeb):            # jmp near
8991cb0ef41Sopenharmony_ci        opcode_bytes += 1
9001cb0ef41Sopenharmony_ci    opcode_percent = (opcode_bytes * 100) / length
9011cb0ef41Sopenharmony_ci    threshold = 20
9021cb0ef41Sopenharmony_ci    if opcode_percent > threshold + 2:
9031cb0ef41Sopenharmony_ci      return True
9041cb0ef41Sopenharmony_ci    if opcode_percent > threshold - 2:
9051cb0ef41Sopenharmony_ci      return None  # Maybe
9061cb0ef41Sopenharmony_ci    return False
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ci  def FindRegion(self, addr):
9091cb0ef41Sopenharmony_ci    answer = [-1, -1]
9101cb0ef41Sopenharmony_ci    def is_in(reader, start, size, location):
9111cb0ef41Sopenharmony_ci      if addr >= start and addr < start + size:
9121cb0ef41Sopenharmony_ci        answer[0] = start
9131cb0ef41Sopenharmony_ci        answer[1] = size
9141cb0ef41Sopenharmony_ci    self.ForEachMemoryRegion(is_in)
9151cb0ef41Sopenharmony_ci    if answer[0] == -1:
9161cb0ef41Sopenharmony_ci      return None
9171cb0ef41Sopenharmony_ci    return answer
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci  def ForEachMemoryRegion(self, cb):
9201cb0ef41Sopenharmony_ci    if self.memory_list64 is not None:
9211cb0ef41Sopenharmony_ci      for r in self.memory_list64.ranges:
9221cb0ef41Sopenharmony_ci        location = self.memory_list64.base_rva + offset
9231cb0ef41Sopenharmony_ci        cb(self, r.start, r.size, location)
9241cb0ef41Sopenharmony_ci        offset += r.size
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci    if self.memory_list is not None:
9271cb0ef41Sopenharmony_ci      for r in self.memory_list.ranges:
9281cb0ef41Sopenharmony_ci        cb(self, r.start, r.memory.data_size, r.memory.rva)
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci  def FindWord(self, word, alignment=0):
9311cb0ef41Sopenharmony_ci    def search_inside_region(reader, start, size, location):
9321cb0ef41Sopenharmony_ci      location = (location + alignment) & ~alignment
9331cb0ef41Sopenharmony_ci      for i in range(size - self.MachinePointerSize()):
9341cb0ef41Sopenharmony_ci        loc = location + i
9351cb0ef41Sopenharmony_ci        if reader._ReadWord(loc) == word:
9361cb0ef41Sopenharmony_ci          slot = start + (loc - location)
9371cb0ef41Sopenharmony_ci          print("%s: %s" % (reader.FormatIntPtr(slot),
9381cb0ef41Sopenharmony_ci                            reader.FormatIntPtr(word)))
9391cb0ef41Sopenharmony_ci    self.ForEachMemoryRegion(search_inside_region)
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_ci  def FindWordList(self, word):
9421cb0ef41Sopenharmony_ci    aligned_res = []
9431cb0ef41Sopenharmony_ci    unaligned_res = []
9441cb0ef41Sopenharmony_ci    def search_inside_region(reader, start, size, location):
9451cb0ef41Sopenharmony_ci      for i in range(size - self.MachinePointerSize()):
9461cb0ef41Sopenharmony_ci        loc = location + i
9471cb0ef41Sopenharmony_ci        if reader._ReadWord(loc) == word:
9481cb0ef41Sopenharmony_ci          slot = start + (loc - location)
9491cb0ef41Sopenharmony_ci          if self.IsAlignedAddress(slot):
9501cb0ef41Sopenharmony_ci            aligned_res.append(slot)
9511cb0ef41Sopenharmony_ci          else:
9521cb0ef41Sopenharmony_ci            unaligned_res.append(slot)
9531cb0ef41Sopenharmony_ci    self.ForEachMemoryRegion(search_inside_region)
9541cb0ef41Sopenharmony_ci    return (aligned_res, unaligned_res)
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  def FindLocation(self, address):
9571cb0ef41Sopenharmony_ci    offset = 0
9581cb0ef41Sopenharmony_ci    if self.memory_list64 is not None:
9591cb0ef41Sopenharmony_ci      for r in self.memory_list64.ranges:
9601cb0ef41Sopenharmony_ci        if r.start <= address < r.start + r.size:
9611cb0ef41Sopenharmony_ci          return self.memory_list64.base_rva + offset + address - r.start
9621cb0ef41Sopenharmony_ci        offset += r.size
9631cb0ef41Sopenharmony_ci    if self.memory_list is not None:
9641cb0ef41Sopenharmony_ci      for r in self.memory_list.ranges:
9651cb0ef41Sopenharmony_ci        if r.start <= address < r.start + r.memory.data_size:
9661cb0ef41Sopenharmony_ci          return r.memory.rva + address - r.start
9671cb0ef41Sopenharmony_ci    return None
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ci  def GetDisasmLines(self, address, size):
9701cb0ef41Sopenharmony_ci    def CountUndefinedInstructions(lines):
9711cb0ef41Sopenharmony_ci      pattern = "<UNDEFINED>"
9721cb0ef41Sopenharmony_ci      return sum([line.count(pattern) for (ignore, line) in lines])
9731cb0ef41Sopenharmony_ci
9741cb0ef41Sopenharmony_ci    location = self.FindLocation(address)
9751cb0ef41Sopenharmony_ci    if location is None: return []
9761cb0ef41Sopenharmony_ci    arch = None
9771cb0ef41Sopenharmony_ci    possible_objdump_flags = [""]
9781cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_X86:
9791cb0ef41Sopenharmony_ci      arch = "ia32"
9801cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM:
9811cb0ef41Sopenharmony_ci      arch = "arm"
9821cb0ef41Sopenharmony_ci      possible_objdump_flags = ["", "--disassembler-options=force-thumb"]
9831cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
9841cb0ef41Sopenharmony_ci      arch = "arm64"
9851cb0ef41Sopenharmony_ci      possible_objdump_flags = ["", "--disassembler-options=force-thumb"]
9861cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_AMD64:
9871cb0ef41Sopenharmony_ci      arch = "x64"
9881cb0ef41Sopenharmony_ci    results = [ disasm.GetDisasmLines(self.minidump_name,
9891cb0ef41Sopenharmony_ci                                     location,
9901cb0ef41Sopenharmony_ci                                     size,
9911cb0ef41Sopenharmony_ci                                     arch,
9921cb0ef41Sopenharmony_ci                                     False,
9931cb0ef41Sopenharmony_ci                                     objdump_flags)
9941cb0ef41Sopenharmony_ci                for objdump_flags in possible_objdump_flags ]
9951cb0ef41Sopenharmony_ci    return min(results, key=CountUndefinedInstructions)
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_ci  def Dispose(self):
9991cb0ef41Sopenharmony_ci    self._reset()
10001cb0ef41Sopenharmony_ci    self.minidump.close()
10011cb0ef41Sopenharmony_ci    self.minidump_file.close()
10021cb0ef41Sopenharmony_ci
10031cb0ef41Sopenharmony_ci  def ExceptionIP(self):
10041cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
10051cb0ef41Sopenharmony_ci      return self.exception_context.rip
10061cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM:
10071cb0ef41Sopenharmony_ci      return self.exception_context.pc
10081cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
10091cb0ef41Sopenharmony_ci      return self.exception_context.pc
10101cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_X86:
10111cb0ef41Sopenharmony_ci      return self.exception_context.eip
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci  def ExceptionSP(self):
10141cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
10151cb0ef41Sopenharmony_ci      return self.exception_context.rsp
10161cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM:
10171cb0ef41Sopenharmony_ci      return self.exception_context.sp
10181cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
10191cb0ef41Sopenharmony_ci      return self.exception_context.sp
10201cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_X86:
10211cb0ef41Sopenharmony_ci      return self.exception_context.esp
10221cb0ef41Sopenharmony_ci
10231cb0ef41Sopenharmony_ci  def ExceptionFP(self):
10241cb0ef41Sopenharmony_ci    if self.arch == MD_CPU_ARCHITECTURE_AMD64:
10251cb0ef41Sopenharmony_ci      return self.exception_context.rbp
10261cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM:
10271cb0ef41Sopenharmony_ci      return None
10281cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_ARM64:
10291cb0ef41Sopenharmony_ci      return self.exception_context.fp
10301cb0ef41Sopenharmony_ci    elif self.arch == MD_CPU_ARCHITECTURE_X86:
10311cb0ef41Sopenharmony_ci      return self.exception_context.ebp
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_ci  def ExceptionThread(self):
10341cb0ef41Sopenharmony_ci    return self.thread_map[self.exception.thread_id]
10351cb0ef41Sopenharmony_ci
10361cb0ef41Sopenharmony_ci  def StackTop(self):
10371cb0ef41Sopenharmony_ci    return self.ExceptionSP()
10381cb0ef41Sopenharmony_ci
10391cb0ef41Sopenharmony_ci  def StackBottom(self):
10401cb0ef41Sopenharmony_ci    exception_thread = self.ExceptionThread()
10411cb0ef41Sopenharmony_ci    return exception_thread.stack.start + \
10421cb0ef41Sopenharmony_ci        exception_thread.stack.memory.data_size
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci  def FormatIntPtr(self, value):
10451cb0ef41Sopenharmony_ci    if self.Is64():
10461cb0ef41Sopenharmony_ci      return "%016x" % value
10471cb0ef41Sopenharmony_ci    return "%08x" % value
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_ci  def FormatTagged(self, value):
10501cb0ef41Sopenharmony_ci    if self.Is64() and not self.IsPointerCompressed():
10511cb0ef41Sopenharmony_ci      return "%016x" % value
10521cb0ef41Sopenharmony_ci    return "%08x" % value
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_ci  def MachinePointerSize(self):
10551cb0ef41Sopenharmony_ci    if self.Is64():
10561cb0ef41Sopenharmony_ci      return 8
10571cb0ef41Sopenharmony_ci    return 4
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  def TaggedPointerSize(self):
10601cb0ef41Sopenharmony_ci    if self.IsPointerCompressed():
10611cb0ef41Sopenharmony_ci      return 4
10621cb0ef41Sopenharmony_ci    return self.MachinePointerSize()
10631cb0ef41Sopenharmony_ci
10641cb0ef41Sopenharmony_ci  def Register(self, name):
10651cb0ef41Sopenharmony_ci    return self.exception_context.__getattribute__(name)
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci  def ReadMinidumpString(self, rva):
10681cb0ef41Sopenharmony_ci    string = bytearray(MINIDUMP_STRING.Read(self.minidump, rva).buffer)
10691cb0ef41Sopenharmony_ci    string = string.decode("utf16")
10701cb0ef41Sopenharmony_ci    return string[0:len(string) - 1]
10711cb0ef41Sopenharmony_ci
10721cb0ef41Sopenharmony_ci  # Load FUNC records from a BreakPad symbol file
10731cb0ef41Sopenharmony_ci  #
10741cb0ef41Sopenharmony_ci  #    http://code.google.com/p/google-breakpad/wiki/SymbolFiles
10751cb0ef41Sopenharmony_ci  #
10761cb0ef41Sopenharmony_ci  def _LoadSymbolsFrom(self, symfile, baseaddr):
10771cb0ef41Sopenharmony_ci    print("Loading symbols from %s" % (symfile))
10781cb0ef41Sopenharmony_ci    funcs = []
10791cb0ef41Sopenharmony_ci    with open(symfile) as f:
10801cb0ef41Sopenharmony_ci      for line in f:
10811cb0ef41Sopenharmony_ci        result = re.match(
10821cb0ef41Sopenharmony_ci            r"^FUNC ([a-f0-9]+) ([a-f0-9]+) ([a-f0-9]+) (.*)$", line)
10831cb0ef41Sopenharmony_ci        if result is not None:
10841cb0ef41Sopenharmony_ci          start = int(result.group(1), 16)
10851cb0ef41Sopenharmony_ci          size = int(result.group(2), 16)
10861cb0ef41Sopenharmony_ci          name = result.group(4).rstrip()
10871cb0ef41Sopenharmony_ci          bisect.insort_left(self.symbols,
10881cb0ef41Sopenharmony_ci                             FuncSymbol(baseaddr + start, size, name))
10891cb0ef41Sopenharmony_ci    print(" ... done")
10901cb0ef41Sopenharmony_ci
10911cb0ef41Sopenharmony_ci  def TryLoadSymbolsFor(self, modulename, module):
10921cb0ef41Sopenharmony_ci    try:
10931cb0ef41Sopenharmony_ci      symfile = os.path.join(self.symdir,
10941cb0ef41Sopenharmony_ci                             modulename.replace('.', '_') + ".pdb.sym")
10951cb0ef41Sopenharmony_ci      if os.path.isfile(symfile):
10961cb0ef41Sopenharmony_ci        self._LoadSymbolsFrom(symfile, module.base_of_image)
10971cb0ef41Sopenharmony_ci        self.modules_with_symbols.append(module)
10981cb0ef41Sopenharmony_ci    except Exception as e:
10991cb0ef41Sopenharmony_ci      print("  ... failure (%s)" % (e))
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  # Returns true if address is covered by some module that has loaded symbols.
11021cb0ef41Sopenharmony_ci  def _IsInModuleWithSymbols(self, addr):
11031cb0ef41Sopenharmony_ci    for module in self.modules_with_symbols:
11041cb0ef41Sopenharmony_ci      start = module.base_of_image
11051cb0ef41Sopenharmony_ci      end = start + module.size_of_image
11061cb0ef41Sopenharmony_ci      if (start <= addr) and (addr < end):
11071cb0ef41Sopenharmony_ci        return True
11081cb0ef41Sopenharmony_ci    return False
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  # Find symbol covering the given address and return its name in format
11111cb0ef41Sopenharmony_ci  #     <symbol name>+<offset from the start>
11121cb0ef41Sopenharmony_ci  def FindSymbol(self, addr):
11131cb0ef41Sopenharmony_ci    if not self._IsInModuleWithSymbols(addr):
11141cb0ef41Sopenharmony_ci      return None
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci    i = bisect.bisect_left(self.symbols, addr)
11171cb0ef41Sopenharmony_ci    symbol = None
11181cb0ef41Sopenharmony_ci    if (0 < i) and self.symbols[i - 1].Covers(addr):
11191cb0ef41Sopenharmony_ci      symbol = self.symbols[i - 1]
11201cb0ef41Sopenharmony_ci    elif (i < len(self.symbols)) and self.symbols[i].Covers(addr):
11211cb0ef41Sopenharmony_ci      symbol = self.symbols[i]
11221cb0ef41Sopenharmony_ci    else:
11231cb0ef41Sopenharmony_ci      return None
11241cb0ef41Sopenharmony_ci    diff = addr - symbol.start
11251cb0ef41Sopenharmony_ci    return "%s+0x%x" % (symbol.name, diff)
11261cb0ef41Sopenharmony_ci
11271cb0ef41Sopenharmony_ci
11281cb0ef41Sopenharmony_ciclass Printer(object):
11291cb0ef41Sopenharmony_ci  """Printer with indentation support."""
11301cb0ef41Sopenharmony_ci
11311cb0ef41Sopenharmony_ci  def __init__(self):
11321cb0ef41Sopenharmony_ci    self.indent = 0
11331cb0ef41Sopenharmony_ci
11341cb0ef41Sopenharmony_ci  def Indent(self):
11351cb0ef41Sopenharmony_ci    self.indent += 2
11361cb0ef41Sopenharmony_ci
11371cb0ef41Sopenharmony_ci  def Dedent(self):
11381cb0ef41Sopenharmony_ci    self.indent -= 2
11391cb0ef41Sopenharmony_ci
11401cb0ef41Sopenharmony_ci  def Print(self, string):
11411cb0ef41Sopenharmony_ci    print("%s%s" % (self._IndentString(), string))
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci  def PrintLines(self, lines):
11441cb0ef41Sopenharmony_ci    indent = self._IndentString()
11451cb0ef41Sopenharmony_ci    print("\n".join("%s%s" % (indent, line) for line in lines))
11461cb0ef41Sopenharmony_ci
11471cb0ef41Sopenharmony_ci  def _IndentString(self):
11481cb0ef41Sopenharmony_ci    return self.indent * " "
11491cb0ef41Sopenharmony_ci
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ciADDRESS_RE = re.compile(r"0x[0-9a-fA-F]+")
11521cb0ef41Sopenharmony_ci
11531cb0ef41Sopenharmony_ci
11541cb0ef41Sopenharmony_cidef FormatDisasmLine(start, heap, line):
11551cb0ef41Sopenharmony_ci  line_address = start + line[0]
11561cb0ef41Sopenharmony_ci  stack_slot = heap.stack_map.get(line_address)
11571cb0ef41Sopenharmony_ci  marker = "  "
11581cb0ef41Sopenharmony_ci  if stack_slot:
11591cb0ef41Sopenharmony_ci    marker = "=>"
11601cb0ef41Sopenharmony_ci  code = AnnotateAddresses(heap, line[1])
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_ci  # Compute the actual call target which the disassembler is too stupid
11631cb0ef41Sopenharmony_ci  # to figure out (it adds the call offset to the disassembly offset rather
11641cb0ef41Sopenharmony_ci  # than the absolute instruction address).
11651cb0ef41Sopenharmony_ci  if heap.reader.arch == MD_CPU_ARCHITECTURE_X86:
11661cb0ef41Sopenharmony_ci    if code.startswith("e8"):
11671cb0ef41Sopenharmony_ci      words = code.split()
11681cb0ef41Sopenharmony_ci      if len(words) > 6 and words[5] == "call":
11691cb0ef41Sopenharmony_ci        offset = int(words[4] + words[3] + words[2] + words[1], 16)
11701cb0ef41Sopenharmony_ci        target = (line_address + offset + 5) & 0xFFFFFFFF
11711cb0ef41Sopenharmony_ci        code = code.replace(words[6], "0x%08x" % target)
11721cb0ef41Sopenharmony_ci  # TODO(jkummerow): port this hack to ARM and x64.
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_ci  return "%s%08x %08x: %s" % (marker, line_address, line[0], code)
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_ci
11771cb0ef41Sopenharmony_cidef AnnotateAddresses(heap, line):
11781cb0ef41Sopenharmony_ci  extra = []
11791cb0ef41Sopenharmony_ci  for m in ADDRESS_RE.finditer(line):
11801cb0ef41Sopenharmony_ci    maybe_address = int(m.group(0), 16)
11811cb0ef41Sopenharmony_ci    object = heap.FindObject(maybe_address)
11821cb0ef41Sopenharmony_ci    if not object: continue
11831cb0ef41Sopenharmony_ci    extra.append(str(object))
11841cb0ef41Sopenharmony_ci  if len(extra) == 0: return line
11851cb0ef41Sopenharmony_ci  return "%s  ;; %s" % (line, ", ".join(extra))
11861cb0ef41Sopenharmony_ci
11871cb0ef41Sopenharmony_ci
11881cb0ef41Sopenharmony_ciclass HeapObject(object):
11891cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
11901cb0ef41Sopenharmony_ci    self.heap = heap
11911cb0ef41Sopenharmony_ci    self.map = map
11921cb0ef41Sopenharmony_ci    self.address = address
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci  def Is(self, cls):
11951cb0ef41Sopenharmony_ci    return isinstance(self, cls)
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci  def Print(self, p):
11981cb0ef41Sopenharmony_ci    p.Print(str(self))
11991cb0ef41Sopenharmony_ci
12001cb0ef41Sopenharmony_ci  def __str__(self):
12011cb0ef41Sopenharmony_ci    instance_type = "???"
12021cb0ef41Sopenharmony_ci    if self.map is not None:
12031cb0ef41Sopenharmony_ci      instance_type = INSTANCE_TYPES[self.map.instance_type]
12041cb0ef41Sopenharmony_ci    return "%s(%s, %s)" % (self.__class__.__name__,
12051cb0ef41Sopenharmony_ci                           self.heap.reader.FormatIntPtr(self.address),
12061cb0ef41Sopenharmony_ci                           instance_type)
12071cb0ef41Sopenharmony_ci
12081cb0ef41Sopenharmony_ci  def ObjectField(self, offset):
12091cb0ef41Sopenharmony_ci    field_value = self.heap.reader.ReadTagged(self.address + offset)
12101cb0ef41Sopenharmony_ci    return self.heap.FindObjectOrSmi(field_value)
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ci  def SmiField(self, offset):
12131cb0ef41Sopenharmony_ci    field_value = self.heap.reader.ReadTagged(self.address + offset)
12141cb0ef41Sopenharmony_ci    if self.heap.IsSmi(field_value):
12151cb0ef41Sopenharmony_ci      return self.heap.SmiUntag(field_value)
12161cb0ef41Sopenharmony_ci    return None
12171cb0ef41Sopenharmony_ci
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_ciclass Map(HeapObject):
12201cb0ef41Sopenharmony_ci  def Decode(self, offset, size, value):
12211cb0ef41Sopenharmony_ci    return (value >> offset) & ((1 << size) - 1)
12221cb0ef41Sopenharmony_ci
12231cb0ef41Sopenharmony_ci  # Instance Sizes
12241cb0ef41Sopenharmony_ci  def InstanceSizesOffset(self):
12251cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
12261cb0ef41Sopenharmony_ci
12271cb0ef41Sopenharmony_ci  def InstanceSizeOffset(self):
12281cb0ef41Sopenharmony_ci    return self.InstanceSizesOffset()
12291cb0ef41Sopenharmony_ci
12301cb0ef41Sopenharmony_ci  def InObjectProperties(self):
12311cb0ef41Sopenharmony_ci    return self.InstanceSizeOffset() + 1
12321cb0ef41Sopenharmony_ci
12331cb0ef41Sopenharmony_ci  def UnusedByte(self):
12341cb0ef41Sopenharmony_ci    return self.InObjectProperties() + 1
12351cb0ef41Sopenharmony_ci
12361cb0ef41Sopenharmony_ci  def VisitorId(self):
12371cb0ef41Sopenharmony_ci    return self.UnusedByte() + 1
12381cb0ef41Sopenharmony_ci
12391cb0ef41Sopenharmony_ci  # Instance Attributes
12401cb0ef41Sopenharmony_ci  def InstanceAttributesOffset(self):
12411cb0ef41Sopenharmony_ci    return self.InstanceSizesOffset() + self.heap.IntSize()
12421cb0ef41Sopenharmony_ci
12431cb0ef41Sopenharmony_ci  def InstanceTypeOffset(self):
12441cb0ef41Sopenharmony_ci    return self.InstanceAttributesOffset()
12451cb0ef41Sopenharmony_ci
12461cb0ef41Sopenharmony_ci  def BitFieldOffset(self):
12471cb0ef41Sopenharmony_ci    return self.InstanceTypeOffset() + 1
12481cb0ef41Sopenharmony_ci
12491cb0ef41Sopenharmony_ci  def BitField2Offset(self):
12501cb0ef41Sopenharmony_ci    return self.BitFieldOffset() + 1
12511cb0ef41Sopenharmony_ci
12521cb0ef41Sopenharmony_ci  def UnusedPropertyFieldsOffset(self):
12531cb0ef41Sopenharmony_ci    return self.BitField2Offset() + 1
12541cb0ef41Sopenharmony_ci
12551cb0ef41Sopenharmony_ci  # Other fields
12561cb0ef41Sopenharmony_ci  def BitField3Offset(self):
12571cb0ef41Sopenharmony_ci    return self.InstanceAttributesOffset() + self.heap.IntSize()
12581cb0ef41Sopenharmony_ci
12591cb0ef41Sopenharmony_ci  def PrototypeOffset(self):
12601cb0ef41Sopenharmony_ci    return self.BitField3Offset() + self.heap.TaggedPointerSize()
12611cb0ef41Sopenharmony_ci
12621cb0ef41Sopenharmony_ci  def ConstructorOrBackPointerOffset(self):
12631cb0ef41Sopenharmony_ci    return self.PrototypeOffset() + self.heap.TaggedPointerSize()
12641cb0ef41Sopenharmony_ci
12651cb0ef41Sopenharmony_ci  def TransitionsOrPrototypeInfoOffset(self):
12661cb0ef41Sopenharmony_ci    return self.ConstructorOrBackPointerOffset() + self.heap.TaggedPointerSize()
12671cb0ef41Sopenharmony_ci
12681cb0ef41Sopenharmony_ci  def DescriptorsOffset(self):
12691cb0ef41Sopenharmony_ci    return (self.TransitionsOrPrototypeInfoOffset() +
12701cb0ef41Sopenharmony_ci            self.heap.TaggedPointerSize())
12711cb0ef41Sopenharmony_ci
12721cb0ef41Sopenharmony_ci  def CodeCacheOffset(self):
12731cb0ef41Sopenharmony_ci    return self.DescriptorsOffset() + self.heap.TaggedPointerSize()
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci  def DependentCodeOffset(self):
12761cb0ef41Sopenharmony_ci    return self.CodeCacheOffset() + self.heap.TaggedPointerSize()
12771cb0ef41Sopenharmony_ci
12781cb0ef41Sopenharmony_ci  def ReadByte(self, offset):
12791cb0ef41Sopenharmony_ci    return self.heap.reader.ReadU8(self.address + offset)
12801cb0ef41Sopenharmony_ci
12811cb0ef41Sopenharmony_ci  def ReadSlot(self, offset):
12821cb0ef41Sopenharmony_ci    return self.heap.reader.ReadTagged(self.address + offset)
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci  def Print(self, p):
12851cb0ef41Sopenharmony_ci    p.Print("Map(%08x)" % (self.address))
12861cb0ef41Sopenharmony_ci    p.Print("  - size: %d, inobject: %d, (unused: %d), visitor: %d" % (
12871cb0ef41Sopenharmony_ci        self.ReadByte(self.InstanceSizeOffset()),
12881cb0ef41Sopenharmony_ci        self.ReadByte(self.InObjectProperties()),
12891cb0ef41Sopenharmony_ci        self.ReadByte(self.UnusedByte()),
12901cb0ef41Sopenharmony_ci        self.VisitorId()))
12911cb0ef41Sopenharmony_ci
12921cb0ef41Sopenharmony_ci    instance_type = INSTANCE_TYPES[self.ReadByte(self.InstanceTypeOffset())]
12931cb0ef41Sopenharmony_ci    bitfield = self.ReadByte(self.BitFieldOffset())
12941cb0ef41Sopenharmony_ci    bitfield2 = self.ReadByte(self.BitField2Offset())
12951cb0ef41Sopenharmony_ci    unused = self.ReadByte(self.UnusedPropertyFieldsOffset())
12961cb0ef41Sopenharmony_ci    p.Print("  - %s, bf: %d, bf2: %d, unused: %d" % (
12971cb0ef41Sopenharmony_ci        instance_type, bitfield, bitfield2, unused))
12981cb0ef41Sopenharmony_ci
12991cb0ef41Sopenharmony_ci    p.Print("  - kind: %s" % (self.Decode(3, 5, bitfield2)))
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci    bitfield3 = self.ReadSlot(self.BitField3Offset())
13021cb0ef41Sopenharmony_ci
13031cb0ef41Sopenharmony_ci    p.Print(
13041cb0ef41Sopenharmony_ci        "  - EnumLength: %d NumberOfOwnDescriptors: %d OwnsDescriptors: %s" % (
13051cb0ef41Sopenharmony_ci            self.Decode(0, 10, bitfield3),
13061cb0ef41Sopenharmony_ci            self.Decode(10, 10, bitfield3),
13071cb0ef41Sopenharmony_ci            self.Decode(21, 1, bitfield3)))
13081cb0ef41Sopenharmony_ci    p.Print("  - DictionaryMap: %s" % (self.Decode(20, 1, bitfield3)))
13091cb0ef41Sopenharmony_ci    p.Print("  - Deprecated: %s" % (self.Decode(23, 1, bitfield3)))
13101cb0ef41Sopenharmony_ci    p.Print("  - IsUnstable: %s" % (self.Decode(24, 1, bitfield3)))
13111cb0ef41Sopenharmony_ci    p.Print("  - NewTargetIsBase: %s" % (self.Decode(27, 1, bitfield3)))
13121cb0ef41Sopenharmony_ci
13131cb0ef41Sopenharmony_ci    descriptors = self.ObjectField(self.DescriptorsOffset())
13141cb0ef41Sopenharmony_ci    if descriptors.__class__ == FixedArray:
13151cb0ef41Sopenharmony_ci      DescriptorArray(descriptors).Print(p)
13161cb0ef41Sopenharmony_ci    else:
13171cb0ef41Sopenharmony_ci      p.Print("  - Descriptors: %s" % (descriptors))
13181cb0ef41Sopenharmony_ci
13191cb0ef41Sopenharmony_ci    transitions = self.ObjectField(self.TransitionsOrPrototypeInfoOffset())
13201cb0ef41Sopenharmony_ci    if transitions.__class__ == FixedArray:
13211cb0ef41Sopenharmony_ci      TransitionArray(transitions).Print(p)
13221cb0ef41Sopenharmony_ci    else:
13231cb0ef41Sopenharmony_ci      p.Print("  - TransitionsOrPrototypeInfo: %s" % (transitions))
13241cb0ef41Sopenharmony_ci
13251cb0ef41Sopenharmony_ci    p.Print("  - Prototype: %s" % self.ObjectField(self.PrototypeOffset()))
13261cb0ef41Sopenharmony_ci
13271cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
13281cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
13291cb0ef41Sopenharmony_ci    self.instance_type = \
13301cb0ef41Sopenharmony_ci        heap.reader.ReadU8(self.address + self.InstanceTypeOffset())
13311cb0ef41Sopenharmony_ci
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ciclass String(HeapObject):
13341cb0ef41Sopenharmony_ci  def LengthOffset(self):
13351cb0ef41Sopenharmony_ci    # First word after the map is the hash, the second is the length.
13361cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize() * 2
13371cb0ef41Sopenharmony_ci
13381cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
13391cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
13401cb0ef41Sopenharmony_ci    self.length = self.SmiField(self.LengthOffset())
13411cb0ef41Sopenharmony_ci
13421cb0ef41Sopenharmony_ci  def GetChars(self):
13431cb0ef41Sopenharmony_ci    return "?string?"
13441cb0ef41Sopenharmony_ci
13451cb0ef41Sopenharmony_ci  def Print(self, p):
13461cb0ef41Sopenharmony_ci    p.Print(str(self))
13471cb0ef41Sopenharmony_ci
13481cb0ef41Sopenharmony_ci  def __str__(self):
13491cb0ef41Sopenharmony_ci    return "\"%s\"" % self.GetChars()
13501cb0ef41Sopenharmony_ci
13511cb0ef41Sopenharmony_ci
13521cb0ef41Sopenharmony_ciclass SeqString(String):
13531cb0ef41Sopenharmony_ci  def CharsOffset(self):
13541cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize() * 3
13551cb0ef41Sopenharmony_ci
13561cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
13571cb0ef41Sopenharmony_ci    String.__init__(self, heap, map, address)
13581cb0ef41Sopenharmony_ci    self.chars = heap.reader.ReadBytes(self.address + self.CharsOffset(),
13591cb0ef41Sopenharmony_ci                                       self.length)
13601cb0ef41Sopenharmony_ci
13611cb0ef41Sopenharmony_ci  def GetChars(self):
13621cb0ef41Sopenharmony_ci    return self.chars
13631cb0ef41Sopenharmony_ci
13641cb0ef41Sopenharmony_ci
13651cb0ef41Sopenharmony_ciclass ExternalString(String):
13661cb0ef41Sopenharmony_ci  # TODO(vegorov) fix ExternalString for X64 architecture
13671cb0ef41Sopenharmony_ci  RESOURCE_OFFSET = 12
13681cb0ef41Sopenharmony_ci
13691cb0ef41Sopenharmony_ci  WEBKIT_RESOUCE_STRING_IMPL_OFFSET = 4
13701cb0ef41Sopenharmony_ci  WEBKIT_STRING_IMPL_CHARS_OFFSET = 8
13711cb0ef41Sopenharmony_ci
13721cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
13731cb0ef41Sopenharmony_ci    String.__init__(self, heap, map, address)
13741cb0ef41Sopenharmony_ci    reader = heap.reader
13751cb0ef41Sopenharmony_ci    self.resource = \
13761cb0ef41Sopenharmony_ci        reader.ReadU32(self.address + ExternalString.RESOURCE_OFFSET)
13771cb0ef41Sopenharmony_ci    self.chars = "?external string?"
13781cb0ef41Sopenharmony_ci    if not reader.IsValidAddress(self.resource): return
13791cb0ef41Sopenharmony_ci    string_impl_address = self.resource + \
13801cb0ef41Sopenharmony_ci        ExternalString.WEBKIT_RESOUCE_STRING_IMPL_OFFSET
13811cb0ef41Sopenharmony_ci    if not reader.IsValidAddress(string_impl_address): return
13821cb0ef41Sopenharmony_ci    string_impl = reader.ReadU32(string_impl_address)
13831cb0ef41Sopenharmony_ci    chars_ptr_address = string_impl + \
13841cb0ef41Sopenharmony_ci        ExternalString.WEBKIT_STRING_IMPL_CHARS_OFFSET
13851cb0ef41Sopenharmony_ci    if not reader.IsValidAddress(chars_ptr_address): return
13861cb0ef41Sopenharmony_ci    chars_ptr = reader.ReadU32(chars_ptr_address)
13871cb0ef41Sopenharmony_ci    if not reader.IsValidAddress(chars_ptr): return
13881cb0ef41Sopenharmony_ci    raw_chars = reader.ReadBytes(chars_ptr, 2 * self.length)
13891cb0ef41Sopenharmony_ci    self.chars = codecs.getdecoder("utf16")(raw_chars)[0]
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_ci  def GetChars(self):
13921cb0ef41Sopenharmony_ci    return self.chars
13931cb0ef41Sopenharmony_ci
13941cb0ef41Sopenharmony_ci
13951cb0ef41Sopenharmony_ciclass ConsString(String):
13961cb0ef41Sopenharmony_ci  def LeftOffset(self):
13971cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize() * 3
13981cb0ef41Sopenharmony_ci
13991cb0ef41Sopenharmony_ci  def RightOffset(self):
14001cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize() * 4
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
14031cb0ef41Sopenharmony_ci    String.__init__(self, heap, map, address)
14041cb0ef41Sopenharmony_ci    self.left = self.ObjectField(self.LeftOffset())
14051cb0ef41Sopenharmony_ci    self.right = self.ObjectField(self.RightOffset())
14061cb0ef41Sopenharmony_ci
14071cb0ef41Sopenharmony_ci  def GetChars(self):
14081cb0ef41Sopenharmony_ci    try:
14091cb0ef41Sopenharmony_ci      return self.left.GetChars() + self.right.GetChars()
14101cb0ef41Sopenharmony_ci    except:
14111cb0ef41Sopenharmony_ci      return "***CAUGHT EXCEPTION IN GROKDUMP***"
14121cb0ef41Sopenharmony_ci
14131cb0ef41Sopenharmony_ci
14141cb0ef41Sopenharmony_ciclass Oddball(HeapObject):
14151cb0ef41Sopenharmony_ci  #Should match declarations in objects.h
14161cb0ef41Sopenharmony_ci  KINDS = [
14171cb0ef41Sopenharmony_ci    "False",
14181cb0ef41Sopenharmony_ci    "True",
14191cb0ef41Sopenharmony_ci    "TheHole",
14201cb0ef41Sopenharmony_ci    "Null",
14211cb0ef41Sopenharmony_ci    "ArgumentMarker",
14221cb0ef41Sopenharmony_ci    "Undefined",
14231cb0ef41Sopenharmony_ci    "Other"
14241cb0ef41Sopenharmony_ci  ]
14251cb0ef41Sopenharmony_ci
14261cb0ef41Sopenharmony_ci  def ToStringOffset(self):
14271cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_ci  def ToNumberOffset(self):
14301cb0ef41Sopenharmony_ci    return self.ToStringOffset() + self.heap.TaggedPointerSize()
14311cb0ef41Sopenharmony_ci
14321cb0ef41Sopenharmony_ci  def KindOffset(self):
14331cb0ef41Sopenharmony_ci    return self.ToNumberOffset() + self.heap.TaggedPointerSize()
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
14361cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
14371cb0ef41Sopenharmony_ci    self.to_string = self.ObjectField(self.ToStringOffset())
14381cb0ef41Sopenharmony_ci    self.kind = self.SmiField(self.KindOffset())
14391cb0ef41Sopenharmony_ci
14401cb0ef41Sopenharmony_ci  def Print(self, p):
14411cb0ef41Sopenharmony_ci    p.Print(str(self))
14421cb0ef41Sopenharmony_ci
14431cb0ef41Sopenharmony_ci  def __str__(self):
14441cb0ef41Sopenharmony_ci    if self.to_string:
14451cb0ef41Sopenharmony_ci      return "Oddball(%08x, <%s>)" % (self.address, str(self.to_string))
14461cb0ef41Sopenharmony_ci    else:
14471cb0ef41Sopenharmony_ci      kind = "???"
14481cb0ef41Sopenharmony_ci      if 0 <= self.kind < len(Oddball.KINDS):
14491cb0ef41Sopenharmony_ci        kind = Oddball.KINDS[self.kind]
14501cb0ef41Sopenharmony_ci      return "Oddball(%08x, kind=%s)" % (self.address, kind)
14511cb0ef41Sopenharmony_ci
14521cb0ef41Sopenharmony_ci
14531cb0ef41Sopenharmony_ciclass FixedArray(HeapObject):
14541cb0ef41Sopenharmony_ci  def LengthOffset(self):
14551cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
14561cb0ef41Sopenharmony_ci
14571cb0ef41Sopenharmony_ci  def ElementsOffset(self):
14581cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize() * 2
14591cb0ef41Sopenharmony_ci
14601cb0ef41Sopenharmony_ci  def MemberOffset(self, i):
14611cb0ef41Sopenharmony_ci    return self.ElementsOffset() + self.heap.TaggedPointerSize() * i
14621cb0ef41Sopenharmony_ci
14631cb0ef41Sopenharmony_ci  def Get(self, i):
14641cb0ef41Sopenharmony_ci    return self.ObjectField(self.MemberOffset(i))
14651cb0ef41Sopenharmony_ci
14661cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
14671cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
14681cb0ef41Sopenharmony_ci    self.length = self.SmiField(self.LengthOffset())
14691cb0ef41Sopenharmony_ci
14701cb0ef41Sopenharmony_ci  def Print(self, p):
14711cb0ef41Sopenharmony_ci    p.Print("FixedArray(%s) {" % self.heap.reader.FormatIntPtr(self.address))
14721cb0ef41Sopenharmony_ci    p.Indent()
14731cb0ef41Sopenharmony_ci    p.Print("length: %d" % self.length)
14741cb0ef41Sopenharmony_ci    base_offset = self.ElementsOffset()
14751cb0ef41Sopenharmony_ci    for i in range(self.length):
14761cb0ef41Sopenharmony_ci      offset = base_offset + 4 * i
14771cb0ef41Sopenharmony_ci      try:
14781cb0ef41Sopenharmony_ci        p.Print("[%08d] = %s" % (i, self.ObjectField(offset)))
14791cb0ef41Sopenharmony_ci      except TypeError:
14801cb0ef41Sopenharmony_ci        p.Dedent()
14811cb0ef41Sopenharmony_ci        p.Print("...")
14821cb0ef41Sopenharmony_ci        p.Print("}")
14831cb0ef41Sopenharmony_ci        return
14841cb0ef41Sopenharmony_ci    p.Dedent()
14851cb0ef41Sopenharmony_ci    p.Print("}")
14861cb0ef41Sopenharmony_ci
14871cb0ef41Sopenharmony_ci  def __str__(self):
14881cb0ef41Sopenharmony_ci    return "FixedArray(%08x, length=%d)" % (self.address, self.length)
14891cb0ef41Sopenharmony_ci
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_ciclass DescriptorArray(object):
14921cb0ef41Sopenharmony_ci  def __init__(self, array):
14931cb0ef41Sopenharmony_ci    self.array = array
14941cb0ef41Sopenharmony_ci
14951cb0ef41Sopenharmony_ci  def Length(self):
14961cb0ef41Sopenharmony_ci    return self.array.Get(0)
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_ci  def Decode(self, offset, size, value):
14991cb0ef41Sopenharmony_ci    return (value >> offset) & ((1 << size) - 1)
15001cb0ef41Sopenharmony_ci
15011cb0ef41Sopenharmony_ci  TYPES = [
15021cb0ef41Sopenharmony_ci      "normal",
15031cb0ef41Sopenharmony_ci      "field",
15041cb0ef41Sopenharmony_ci      "function",
15051cb0ef41Sopenharmony_ci      "callbacks"
15061cb0ef41Sopenharmony_ci  ]
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci  def Type(self, value):
15091cb0ef41Sopenharmony_ci    return DescriptorArray.TYPES[self.Decode(0, 3, value)]
15101cb0ef41Sopenharmony_ci
15111cb0ef41Sopenharmony_ci  def Attributes(self, value):
15121cb0ef41Sopenharmony_ci    attributes = self.Decode(3, 3, value)
15131cb0ef41Sopenharmony_ci    result = []
15141cb0ef41Sopenharmony_ci    if (attributes & 0): result += ["ReadOnly"]
15151cb0ef41Sopenharmony_ci    if (attributes & 1): result += ["DontEnum"]
15161cb0ef41Sopenharmony_ci    if (attributes & 2): result += ["DontDelete"]
15171cb0ef41Sopenharmony_ci    return "[" + (",".join(result)) + "]"
15181cb0ef41Sopenharmony_ci
15191cb0ef41Sopenharmony_ci  def Deleted(self, value):
15201cb0ef41Sopenharmony_ci    return self.Decode(6, 1, value) == 1
15211cb0ef41Sopenharmony_ci
15221cb0ef41Sopenharmony_ci  def FieldIndex(self, value):
15231cb0ef41Sopenharmony_ci    return self.Decode(20, 11, value)
15241cb0ef41Sopenharmony_ci
15251cb0ef41Sopenharmony_ci  def Pointer(self, value):
15261cb0ef41Sopenharmony_ci    return self.Decode(6, 11, value)
15271cb0ef41Sopenharmony_ci
15281cb0ef41Sopenharmony_ci  def Details(self, di, value):
15291cb0ef41Sopenharmony_ci    return (
15301cb0ef41Sopenharmony_ci        di,
15311cb0ef41Sopenharmony_ci        self.Type(value),
15321cb0ef41Sopenharmony_ci        self.Attributes(value),
15331cb0ef41Sopenharmony_ci        self.FieldIndex(value),
15341cb0ef41Sopenharmony_ci        self.Pointer(value)
15351cb0ef41Sopenharmony_ci    )
15361cb0ef41Sopenharmony_ci
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci  def Print(self, p):
15391cb0ef41Sopenharmony_ci    length = self.Length()
15401cb0ef41Sopenharmony_ci    array = self.array
15411cb0ef41Sopenharmony_ci
15421cb0ef41Sopenharmony_ci    p.Print("Descriptors(%08x, length=%d)" % (array.address, length))
15431cb0ef41Sopenharmony_ci    p.Print("[et] %s" % (array.Get(1)))
15441cb0ef41Sopenharmony_ci
15451cb0ef41Sopenharmony_ci    for di in range(length):
15461cb0ef41Sopenharmony_ci      i = 2 + di * 3
15471cb0ef41Sopenharmony_ci      p.Print("0x%x" % (array.address + array.MemberOffset(i)))
15481cb0ef41Sopenharmony_ci      p.Print("[%i] name:    %s" % (di, array.Get(i + 0)))
15491cb0ef41Sopenharmony_ci      p.Print("[%i] details: %s %s field-index %i pointer %i" % \
15501cb0ef41Sopenharmony_ci              self.Details(di, array.Get(i + 1)))
15511cb0ef41Sopenharmony_ci      p.Print("[%i] value:   %s" % (di, array.Get(i + 2)))
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_ci    end = self.array.length // 3
15541cb0ef41Sopenharmony_ci    if length != end:
15551cb0ef41Sopenharmony_ci      p.Print("[%i-%i] slack descriptors" % (length, end))
15561cb0ef41Sopenharmony_ci
15571cb0ef41Sopenharmony_ci
15581cb0ef41Sopenharmony_ciclass TransitionArray(object):
15591cb0ef41Sopenharmony_ci  def __init__(self, array):
15601cb0ef41Sopenharmony_ci    self.array = array
15611cb0ef41Sopenharmony_ci
15621cb0ef41Sopenharmony_ci  def IsSimpleTransition(self):
15631cb0ef41Sopenharmony_ci    return self.array.length <= 2
15641cb0ef41Sopenharmony_ci
15651cb0ef41Sopenharmony_ci  def Length(self):
15661cb0ef41Sopenharmony_ci    # SimpleTransition cases
15671cb0ef41Sopenharmony_ci    if self.IsSimpleTransition():
15681cb0ef41Sopenharmony_ci      return self.array.length - 1
15691cb0ef41Sopenharmony_ci    return (self.array.length - 3) // 2
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_ci  def Print(self, p):
15721cb0ef41Sopenharmony_ci    length = self.Length()
15731cb0ef41Sopenharmony_ci    array = self.array
15741cb0ef41Sopenharmony_ci
15751cb0ef41Sopenharmony_ci    p.Print("Transitions(%08x, length=%d)" % (array.address, length))
15761cb0ef41Sopenharmony_ci    p.Print("[backpointer] %s" % (array.Get(0)))
15771cb0ef41Sopenharmony_ci    if self.IsSimpleTransition():
15781cb0ef41Sopenharmony_ci      if length == 1:
15791cb0ef41Sopenharmony_ci        p.Print("[simple target] %s" % (array.Get(1)))
15801cb0ef41Sopenharmony_ci      return
15811cb0ef41Sopenharmony_ci
15821cb0ef41Sopenharmony_ci    elements = array.Get(1)
15831cb0ef41Sopenharmony_ci    if elements is not None:
15841cb0ef41Sopenharmony_ci      p.Print("[elements   ] %s" % (elements))
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_ci    prototype = array.Get(2)
15871cb0ef41Sopenharmony_ci    if prototype is not None:
15881cb0ef41Sopenharmony_ci      p.Print("[prototype  ] %s" % (prototype))
15891cb0ef41Sopenharmony_ci
15901cb0ef41Sopenharmony_ci    for di in range(length):
15911cb0ef41Sopenharmony_ci      i = 3 + di * 2
15921cb0ef41Sopenharmony_ci      p.Print("[%i] symbol: %s" % (di, array.Get(i + 0)))
15931cb0ef41Sopenharmony_ci      p.Print("[%i] target: %s" % (di, array.Get(i + 1)))
15941cb0ef41Sopenharmony_ci
15951cb0ef41Sopenharmony_ci
15961cb0ef41Sopenharmony_ciclass JSFunction(HeapObject):
15971cb0ef41Sopenharmony_ci  def CodeEntryOffset(self):
15981cb0ef41Sopenharmony_ci    return 3 * self.heap.TaggedPointerSize()
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_ci  def SharedOffset(self):
16011cb0ef41Sopenharmony_ci    return 5 * self.heap.TaggedPointerSize()
16021cb0ef41Sopenharmony_ci
16031cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
16041cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
16051cb0ef41Sopenharmony_ci    code_entry = \
16061cb0ef41Sopenharmony_ci        heap.reader.ReadU32(self.address + self.CodeEntryOffset())
16071cb0ef41Sopenharmony_ci    self.code = heap.FindObject(code_entry - Code.HeaderSize(heap) + 1)
16081cb0ef41Sopenharmony_ci    self.shared = self.ObjectField(self.SharedOffset())
16091cb0ef41Sopenharmony_ci
16101cb0ef41Sopenharmony_ci  def Print(self, p):
16111cb0ef41Sopenharmony_ci    source = "\n".join("  %s" % line for line in self._GetSource().split("\n"))
16121cb0ef41Sopenharmony_ci    p.Print("JSFunction(%s) {" % self.heap.reader.FormatIntPtr(self.address))
16131cb0ef41Sopenharmony_ci    p.Indent()
16141cb0ef41Sopenharmony_ci    p.Print("inferred name: %s" % self.shared.inferred_name)
16151cb0ef41Sopenharmony_ci    if self.shared.script.Is(Script) and self.shared.script.name.Is(String):
16161cb0ef41Sopenharmony_ci      p.Print("script name: %s" % self.shared.script.name)
16171cb0ef41Sopenharmony_ci    p.Print("source:")
16181cb0ef41Sopenharmony_ci    p.PrintLines(self._GetSource().split("\n"))
16191cb0ef41Sopenharmony_ci    p.Print("code:")
16201cb0ef41Sopenharmony_ci    self.code.Print(p)
16211cb0ef41Sopenharmony_ci    if self.code != self.shared.code:
16221cb0ef41Sopenharmony_ci      p.Print("unoptimized code:")
16231cb0ef41Sopenharmony_ci      self.shared.code.Print(p)
16241cb0ef41Sopenharmony_ci    p.Dedent()
16251cb0ef41Sopenharmony_ci    p.Print("}")
16261cb0ef41Sopenharmony_ci
16271cb0ef41Sopenharmony_ci  def __str__(self):
16281cb0ef41Sopenharmony_ci    inferred_name = ""
16291cb0ef41Sopenharmony_ci    if self.shared is not None and self.shared.Is(SharedFunctionInfo):
16301cb0ef41Sopenharmony_ci      inferred_name = self.shared.inferred_name
16311cb0ef41Sopenharmony_ci    return "JSFunction(%s, %s) " % \
16321cb0ef41Sopenharmony_ci          (self.heap.reader.FormatIntPtr(self.address), inferred_name)
16331cb0ef41Sopenharmony_ci
16341cb0ef41Sopenharmony_ci  def _GetSource(self):
16351cb0ef41Sopenharmony_ci    source = "?source?"
16361cb0ef41Sopenharmony_ci    start = self.shared.start_position
16371cb0ef41Sopenharmony_ci    end = self.shared.end_position
16381cb0ef41Sopenharmony_ci    if not self.shared.script.Is(Script): return source
16391cb0ef41Sopenharmony_ci    script_source = self.shared.script.source
16401cb0ef41Sopenharmony_ci    if not script_source.Is(String): return source
16411cb0ef41Sopenharmony_ci    if start and end:
16421cb0ef41Sopenharmony_ci      source = script_source.GetChars()[start:end]
16431cb0ef41Sopenharmony_ci    return source
16441cb0ef41Sopenharmony_ci
16451cb0ef41Sopenharmony_ci
16461cb0ef41Sopenharmony_ciclass SharedFunctionInfo(HeapObject):
16471cb0ef41Sopenharmony_ci  def CodeOffset(self):
16481cb0ef41Sopenharmony_ci    return 2 * self.heap.TaggedPointerSize()
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci  def ScriptOffset(self):
16511cb0ef41Sopenharmony_ci    return 7 * self.heap.TaggedPointerSize()
16521cb0ef41Sopenharmony_ci
16531cb0ef41Sopenharmony_ci  def InferredNameOffset(self):
16541cb0ef41Sopenharmony_ci    return 9 * self.heap.TaggedPointerSize()
16551cb0ef41Sopenharmony_ci
16561cb0ef41Sopenharmony_ci  def EndPositionOffset(self):
16571cb0ef41Sopenharmony_ci    return 12 * self.heap.TaggedPointerSize() + 4 * self.heap.IntSize()
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_ci  def StartPositionAndTypeOffset(self):
16601cb0ef41Sopenharmony_ci    return 12 * self.heap.TaggedPointerSize() + 5 * self.heap.IntSize()
16611cb0ef41Sopenharmony_ci
16621cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
16631cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
16641cb0ef41Sopenharmony_ci    try:
16651cb0ef41Sopenharmony_ci      self.code = self.ObjectField(self.CodeOffset())
16661cb0ef41Sopenharmony_ci      self.script = self.ObjectField(self.ScriptOffset())
16671cb0ef41Sopenharmony_ci      self.inferred_name = self.ObjectField(self.InferredNameOffset())
16681cb0ef41Sopenharmony_ci      if heap.TaggedPointerSize() == 8:
16691cb0ef41Sopenharmony_ci        start_position_and_type = \
16701cb0ef41Sopenharmony_ci            heap.reader.ReadU32(self.StartPositionAndTypeOffset())
16711cb0ef41Sopenharmony_ci        self.start_position = start_position_and_type >> 2
16721cb0ef41Sopenharmony_ci        pseudo_smi_end_position = \
16731cb0ef41Sopenharmony_ci            heap.reader.ReadU32(self.EndPositionOffset())
16741cb0ef41Sopenharmony_ci        self.end_position = pseudo_smi_end_position >> 2
16751cb0ef41Sopenharmony_ci      else:
16761cb0ef41Sopenharmony_ci        start_position_and_type = \
16771cb0ef41Sopenharmony_ci            self.SmiField(self.StartPositionAndTypeOffset())
16781cb0ef41Sopenharmony_ci        if start_position_and_type:
16791cb0ef41Sopenharmony_ci          self.start_position = start_position_and_type >> 2
16801cb0ef41Sopenharmony_ci        else:
16811cb0ef41Sopenharmony_ci          self.start_position = None
16821cb0ef41Sopenharmony_ci        self.end_position = \
16831cb0ef41Sopenharmony_ci            self.SmiField(self.EndPositionOffset())
16841cb0ef41Sopenharmony_ci    except:
16851cb0ef41Sopenharmony_ci      print("*** Error while reading SharedFunctionInfo")
16861cb0ef41Sopenharmony_ci
16871cb0ef41Sopenharmony_ci
16881cb0ef41Sopenharmony_ciclass Script(HeapObject):
16891cb0ef41Sopenharmony_ci  def SourceOffset(self):
16901cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
16911cb0ef41Sopenharmony_ci
16921cb0ef41Sopenharmony_ci  def NameOffset(self):
16931cb0ef41Sopenharmony_ci    return self.SourceOffset() + self.heap.TaggedPointerSize()
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
16961cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
16971cb0ef41Sopenharmony_ci    self.source = self.ObjectField(self.SourceOffset())
16981cb0ef41Sopenharmony_ci    self.name = self.ObjectField(self.NameOffset())
16991cb0ef41Sopenharmony_ci
17001cb0ef41Sopenharmony_ci
17011cb0ef41Sopenharmony_ciclass CodeCache(HeapObject):
17021cb0ef41Sopenharmony_ci  def DefaultCacheOffset(self):
17031cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
17041cb0ef41Sopenharmony_ci
17051cb0ef41Sopenharmony_ci  def NormalTypeCacheOffset(self):
17061cb0ef41Sopenharmony_ci    return self.DefaultCacheOffset() + self.heap.TaggedPointerSize()
17071cb0ef41Sopenharmony_ci
17081cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
17091cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
17101cb0ef41Sopenharmony_ci    self.default_cache = self.ObjectField(self.DefaultCacheOffset())
17111cb0ef41Sopenharmony_ci    self.normal_type_cache = self.ObjectField(self.NormalTypeCacheOffset())
17121cb0ef41Sopenharmony_ci
17131cb0ef41Sopenharmony_ci  def Print(self, p):
17141cb0ef41Sopenharmony_ci    p.Print("CodeCache(%s) {" % self.heap.reader.FormatIntPtr(self.address))
17151cb0ef41Sopenharmony_ci    p.Indent()
17161cb0ef41Sopenharmony_ci    p.Print("default cache: %s" % self.default_cache)
17171cb0ef41Sopenharmony_ci    p.Print("normal type cache: %s" % self.normal_type_cache)
17181cb0ef41Sopenharmony_ci    p.Dedent()
17191cb0ef41Sopenharmony_ci    p.Print("}")
17201cb0ef41Sopenharmony_ci
17211cb0ef41Sopenharmony_ci
17221cb0ef41Sopenharmony_ciclass Code(HeapObject):
17231cb0ef41Sopenharmony_ci  CODE_ALIGNMENT_MASK = (1 << 5) - 1
17241cb0ef41Sopenharmony_ci
17251cb0ef41Sopenharmony_ci  def InstructionSizeOffset(self):
17261cb0ef41Sopenharmony_ci    return self.heap.TaggedPointerSize()
17271cb0ef41Sopenharmony_ci
17281cb0ef41Sopenharmony_ci  @staticmethod
17291cb0ef41Sopenharmony_ci  def HeaderSize(heap):
17301cb0ef41Sopenharmony_ci    return (heap.TaggedPointerSize() + heap.IntSize() + \
17311cb0ef41Sopenharmony_ci        4 * heap.TaggedPointerSize() + 3 * heap.IntSize() + \
17321cb0ef41Sopenharmony_ci        Code.CODE_ALIGNMENT_MASK) & ~Code.CODE_ALIGNMENT_MASK
17331cb0ef41Sopenharmony_ci
17341cb0ef41Sopenharmony_ci  def __init__(self, heap, map, address):
17351cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, map, address)
17361cb0ef41Sopenharmony_ci    self.entry = self.address + Code.HeaderSize(heap)
17371cb0ef41Sopenharmony_ci    self.instruction_size = \
17381cb0ef41Sopenharmony_ci        heap.reader.ReadU32(self.address + self.InstructionSizeOffset())
17391cb0ef41Sopenharmony_ci
17401cb0ef41Sopenharmony_ci  def Print(self, p):
17411cb0ef41Sopenharmony_ci    lines = self.heap.reader.GetDisasmLines(self.entry, self.instruction_size)
17421cb0ef41Sopenharmony_ci    p.Print("Code(%s) {" % self.heap.reader.FormatIntPtr(self.address))
17431cb0ef41Sopenharmony_ci    p.Indent()
17441cb0ef41Sopenharmony_ci    p.Print("instruction_size: %d" % self.instruction_size)
17451cb0ef41Sopenharmony_ci    p.PrintLines(self._FormatLine(line) for line in lines)
17461cb0ef41Sopenharmony_ci    p.Dedent()
17471cb0ef41Sopenharmony_ci    p.Print("}")
17481cb0ef41Sopenharmony_ci
17491cb0ef41Sopenharmony_ci  def _FormatLine(self, line):
17501cb0ef41Sopenharmony_ci    return FormatDisasmLine(self.entry, self.heap, line)
17511cb0ef41Sopenharmony_ci
17521cb0ef41Sopenharmony_ci
17531cb0ef41Sopenharmony_ciclass V8Heap(object):
17541cb0ef41Sopenharmony_ci  CLASS_MAP = {
17551cb0ef41Sopenharmony_ci    "SYMBOL_TYPE": SeqString,
17561cb0ef41Sopenharmony_ci    "ONE_BYTE_SYMBOL_TYPE": SeqString,
17571cb0ef41Sopenharmony_ci    "CONS_SYMBOL_TYPE": ConsString,
17581cb0ef41Sopenharmony_ci    "CONS_ONE_BYTE_SYMBOL_TYPE": ConsString,
17591cb0ef41Sopenharmony_ci    "EXTERNAL_SYMBOL_TYPE": ExternalString,
17601cb0ef41Sopenharmony_ci    "EXTERNAL_SYMBOL_WITH_ONE_BYTE_DATA_TYPE": ExternalString,
17611cb0ef41Sopenharmony_ci    "EXTERNAL_ONE_BYTE_SYMBOL_TYPE": ExternalString,
17621cb0ef41Sopenharmony_ci    "UNCACHED_EXTERNAL_SYMBOL_TYPE": ExternalString,
17631cb0ef41Sopenharmony_ci    "UNCACHED_EXTERNAL_SYMBOL_WITH_ONE_BYTE_DATA_TYPE": ExternalString,
17641cb0ef41Sopenharmony_ci    "UNCACHED_EXTERNAL_ONE_BYTE_SYMBOL_TYPE": ExternalString,
17651cb0ef41Sopenharmony_ci    "STRING_TYPE": SeqString,
17661cb0ef41Sopenharmony_ci    "ONE_BYTE_STRING_TYPE": SeqString,
17671cb0ef41Sopenharmony_ci    "CONS_STRING_TYPE": ConsString,
17681cb0ef41Sopenharmony_ci    "CONS_ONE_BYTE_STRING_TYPE": ConsString,
17691cb0ef41Sopenharmony_ci    "EXTERNAL_STRING_TYPE": ExternalString,
17701cb0ef41Sopenharmony_ci    "EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE": ExternalString,
17711cb0ef41Sopenharmony_ci    "EXTERNAL_ONE_BYTE_STRING_TYPE": ExternalString,
17721cb0ef41Sopenharmony_ci    "MAP_TYPE": Map,
17731cb0ef41Sopenharmony_ci    "ODDBALL_TYPE": Oddball,
17741cb0ef41Sopenharmony_ci    "FIXED_ARRAY_TYPE": FixedArray,
17751cb0ef41Sopenharmony_ci    "HASH_TABLE_TYPE": FixedArray,
17761cb0ef41Sopenharmony_ci    "OBJECT_BOILERPLATE_DESCRIPTION_TYPE": FixedArray,
17771cb0ef41Sopenharmony_ci    "SCOPE_INFO_TYPE": FixedArray,
17781cb0ef41Sopenharmony_ci    "JS_FUNCTION_TYPE": JSFunction,
17791cb0ef41Sopenharmony_ci    "SHARED_FUNCTION_INFO_TYPE": SharedFunctionInfo,
17801cb0ef41Sopenharmony_ci    "SCRIPT_TYPE": Script,
17811cb0ef41Sopenharmony_ci    "CODE_CACHE_TYPE": CodeCache,
17821cb0ef41Sopenharmony_ci    "CODE_TYPE": Code,
17831cb0ef41Sopenharmony_ci  }
17841cb0ef41Sopenharmony_ci
17851cb0ef41Sopenharmony_ci  def __init__(self, reader, stack_map):
17861cb0ef41Sopenharmony_ci    self.reader = reader
17871cb0ef41Sopenharmony_ci    self.stack_map = stack_map
17881cb0ef41Sopenharmony_ci    self.objects = {}
17891cb0ef41Sopenharmony_ci
17901cb0ef41Sopenharmony_ci  def FindObjectOrSmi(self, tagged_address):
17911cb0ef41Sopenharmony_ci    if self.IsSmi(tagged_address): return self.SmiUntag(tagged_address)
17921cb0ef41Sopenharmony_ci    return self.FindObject(tagged_address)
17931cb0ef41Sopenharmony_ci
17941cb0ef41Sopenharmony_ci  def FindObject(self, tagged_address):
17951cb0ef41Sopenharmony_ci    if tagged_address in self.objects:
17961cb0ef41Sopenharmony_ci      return self.objects[tagged_address]
17971cb0ef41Sopenharmony_ci    if not self.IsTaggedObjectAddress(tagged_address): return None
17981cb0ef41Sopenharmony_ci    address = tagged_address - 1
17991cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(address): return None
18001cb0ef41Sopenharmony_ci    map_tagged_address = self.reader.ReadTagged(address)
18011cb0ef41Sopenharmony_ci    if tagged_address == map_tagged_address:
18021cb0ef41Sopenharmony_ci      # Meta map?
18031cb0ef41Sopenharmony_ci      meta_map = Map(self, None, address)
18041cb0ef41Sopenharmony_ci      instance_type_name = INSTANCE_TYPES.get(meta_map.instance_type)
18051cb0ef41Sopenharmony_ci      if instance_type_name != "MAP_TYPE": return None
18061cb0ef41Sopenharmony_ci      meta_map.map = meta_map
18071cb0ef41Sopenharmony_ci      object = meta_map
18081cb0ef41Sopenharmony_ci    else:
18091cb0ef41Sopenharmony_ci      map = self.FindMap(map_tagged_address)
18101cb0ef41Sopenharmony_ci      if map is None: return None
18111cb0ef41Sopenharmony_ci      instance_type_name = INSTANCE_TYPES.get(map.instance_type)
18121cb0ef41Sopenharmony_ci      if instance_type_name is None: return None
18131cb0ef41Sopenharmony_ci      cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
18141cb0ef41Sopenharmony_ci      object = cls(self, map, address)
18151cb0ef41Sopenharmony_ci    self.objects[tagged_address] = object
18161cb0ef41Sopenharmony_ci    return object
18171cb0ef41Sopenharmony_ci
18181cb0ef41Sopenharmony_ci  def FindMap(self, tagged_address):
18191cb0ef41Sopenharmony_ci    address = self.FindMapAddress(tagged_address)
18201cb0ef41Sopenharmony_ci    if not address: return None
18211cb0ef41Sopenharmony_ci    object = Map(self, None, address)
18221cb0ef41Sopenharmony_ci    return object
18231cb0ef41Sopenharmony_ci
18241cb0ef41Sopenharmony_ci  def FindMapAddress(self, tagged_address):
18251cb0ef41Sopenharmony_ci    if not self.IsTaggedMapAddress(tagged_address): return None
18261cb0ef41Sopenharmony_ci    address = tagged_address - 1
18271cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(address): return None
18281cb0ef41Sopenharmony_ci    return address
18291cb0ef41Sopenharmony_ci
18301cb0ef41Sopenharmony_ci  def IntSize(self):
18311cb0ef41Sopenharmony_ci    return 4
18321cb0ef41Sopenharmony_ci
18331cb0ef41Sopenharmony_ci  def MachinePointerSize(self):
18341cb0ef41Sopenharmony_ci    return self.reader.MachinePointerSize()
18351cb0ef41Sopenharmony_ci
18361cb0ef41Sopenharmony_ci  def TaggedPointerSize(self):
18371cb0ef41Sopenharmony_ci    return self.reader.TaggedPointerSize()
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_ci  def IsPointerCompressed(self):
18401cb0ef41Sopenharmony_ci    return self.reader.IsPointerCompressed()
18411cb0ef41Sopenharmony_ci
18421cb0ef41Sopenharmony_ci  def ObjectAlignmentMask(self):
18431cb0ef41Sopenharmony_ci    return self.TaggedPointerSize() - 1
18441cb0ef41Sopenharmony_ci
18451cb0ef41Sopenharmony_ci  def IsTaggedObjectAddress(self, address):
18461cb0ef41Sopenharmony_ci    return (address & self.ObjectAlignmentMask()) == 1
18471cb0ef41Sopenharmony_ci
18481cb0ef41Sopenharmony_ci  def IsValidTaggedObjectAddress(self, address):
18491cb0ef41Sopenharmony_ci    if not self.IsTaggedObjectAddress(address): return False
18501cb0ef41Sopenharmony_ci    return self.reader.IsValidAddress(address)
18511cb0ef41Sopenharmony_ci
18521cb0ef41Sopenharmony_ci  def IsTaggedMapAddress(self, address):
18531cb0ef41Sopenharmony_ci    return (address & self.MapAlignmentMask()) == 1
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_ci  def MapAlignmentMask(self):
18561cb0ef41Sopenharmony_ci    if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64:
18571cb0ef41Sopenharmony_ci      return (1 << 4) - 1
18581cb0ef41Sopenharmony_ci    elif self.reader.arch == MD_CPU_ARCHITECTURE_ARM:
18591cb0ef41Sopenharmony_ci      return (1 << 4) - 1
18601cb0ef41Sopenharmony_ci    elif self.reader.arch == MD_CPU_ARCHITECTURE_ARM64:
18611cb0ef41Sopenharmony_ci      return (1 << 4) - 1
18621cb0ef41Sopenharmony_ci    elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
18631cb0ef41Sopenharmony_ci      return (1 << 5) - 1
18641cb0ef41Sopenharmony_ci
18651cb0ef41Sopenharmony_ci  def PageAlignmentMask(self):
18661cb0ef41Sopenharmony_ci    return (1 << 19) - 1
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ci  def IsTaggedAddress(self, address):
18691cb0ef41Sopenharmony_ci    return (address & self.ObjectAlignmentMask()) == 1
18701cb0ef41Sopenharmony_ci
18711cb0ef41Sopenharmony_ci  def IsSmi(self, tagged_address):
18721cb0ef41Sopenharmony_ci    if self.reader.Is64() and not self.reader.IsPointerCompressed():
18731cb0ef41Sopenharmony_ci      return (tagged_address & 0xFFFFFFFF) == 0
18741cb0ef41Sopenharmony_ci    return not self.IsTaggedAddress(tagged_address)
18751cb0ef41Sopenharmony_ci
18761cb0ef41Sopenharmony_ci  def SmiUntag(self, tagged_address):
18771cb0ef41Sopenharmony_ci    if self.reader.Is64() and not self.reader.IsPointerCompressed():
18781cb0ef41Sopenharmony_ci      return tagged_address >> 32
18791cb0ef41Sopenharmony_ci    return (tagged_address >> 1) & 0xFFFFFFFF
18801cb0ef41Sopenharmony_ci
18811cb0ef41Sopenharmony_ci  def AddressTypeMarker(self, address):
18821cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(address): return " "
18831cb0ef41Sopenharmony_ci    if self.reader.IsExceptionStackAddress(address): return "S"
18841cb0ef41Sopenharmony_ci    if self.reader.IsModuleAddress(address): return "C"
18851cb0ef41Sopenharmony_ci    if self.IsTaggedAddress(address):
18861cb0ef41Sopenharmony_ci      # Cannot have an tagged pointer into the stack
18871cb0ef41Sopenharmony_ci      if self.reader.IsAnyExceptionStackAddress(address): return "s"
18881cb0ef41Sopenharmony_ci      return "T"
18891cb0ef41Sopenharmony_ci    return "*"
18901cb0ef41Sopenharmony_ci
18911cb0ef41Sopenharmony_ci  def FormatIntPtr(self, address):
18921cb0ef41Sopenharmony_ci    marker = self.AddressTypeMarker(address)
18931cb0ef41Sopenharmony_ci    address = self.reader.FormatIntPtr(address)
18941cb0ef41Sopenharmony_ci    if marker == " ": return address
18951cb0ef41Sopenharmony_ci    return "%s %s" % (address, marker)
18961cb0ef41Sopenharmony_ci
18971cb0ef41Sopenharmony_ci  def RelativeOffset(self, slot, address):
18981cb0ef41Sopenharmony_ci    if not self.reader.IsValidAlignedAddress(slot): return None
18991cb0ef41Sopenharmony_ci    if self.IsTaggedObjectAddress(address):
19001cb0ef41Sopenharmony_ci      address -= 1
19011cb0ef41Sopenharmony_ci    if not self.reader.IsValidAlignedAddress(address): return None
19021cb0ef41Sopenharmony_ci    offset = (address - slot) / self.MachinePointerSize()
19031cb0ef41Sopenharmony_ci
19041cb0ef41Sopenharmony_ci    lower_limit = -32
19051cb0ef41Sopenharmony_ci    upper_limit = 128
19061cb0ef41Sopenharmony_ci    if self.reader.IsExceptionStackAddress(address):
19071cb0ef41Sopenharmony_ci      upper_limit = 0xFFFFFF
19081cb0ef41Sopenharmony_ci
19091cb0ef41Sopenharmony_ci    if offset < lower_limit or upper_limit < offset: return None
19101cb0ef41Sopenharmony_ci    target_address = self.reader.ReadUIntPtr(address)
19111cb0ef41Sopenharmony_ci    return "[%+02d]=%s %s" % (offset, self.reader.FormatIntPtr(target_address),
19121cb0ef41Sopenharmony_ci                             self.AddressTypeMarker(target_address))
19131cb0ef41Sopenharmony_ci
19141cb0ef41Sopenharmony_ci  def FindObjectPointers(self, start=0, end=0):
19151cb0ef41Sopenharmony_ci    objects = set()
19161cb0ef41Sopenharmony_ci    def find_object_in_region(reader, start, size, location):
19171cb0ef41Sopenharmony_ci      for slot in range(start, start + size, self.reader.TaggedPointerSize()):
19181cb0ef41Sopenharmony_ci        if not self.reader.IsValidAddress(slot): break
19191cb0ef41Sopenharmony_ci        # Collect only tagged pointers (object) to tagged pointers (map)
19201cb0ef41Sopenharmony_ci        tagged_address = self.reader.ReadTagged(slot)
19211cb0ef41Sopenharmony_ci        if not self.IsValidTaggedObjectAddress(tagged_address): continue
19221cb0ef41Sopenharmony_ci        map_address = self.reader.ReadTagged(tagged_address - 1)
19231cb0ef41Sopenharmony_ci        if not self.IsTaggedMapAddress(map_address): continue
19241cb0ef41Sopenharmony_ci        objects.add(tagged_address)
19251cb0ef41Sopenharmony_ci
19261cb0ef41Sopenharmony_ci    if not start and not end:
19271cb0ef41Sopenharmony_ci      self.reader.ForEachMemoryRegion(find_object_in_region)
19281cb0ef41Sopenharmony_ci    else:
19291cb0ef41Sopenharmony_ci      find_object_in_region(self.reader, start, end-start, None)
19301cb0ef41Sopenharmony_ci
19311cb0ef41Sopenharmony_ci    return objects
19321cb0ef41Sopenharmony_ci
19331cb0ef41Sopenharmony_ciclass KnownObject(HeapObject):
19341cb0ef41Sopenharmony_ci  def __init__(self, heap, known_name):
19351cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, None, None)
19361cb0ef41Sopenharmony_ci    self.known_name = known_name
19371cb0ef41Sopenharmony_ci
19381cb0ef41Sopenharmony_ci  def __str__(self):
19391cb0ef41Sopenharmony_ci    return "<%s>" % self.known_name
19401cb0ef41Sopenharmony_ci
19411cb0ef41Sopenharmony_ci
19421cb0ef41Sopenharmony_ciclass KnownMap(HeapObject):
19431cb0ef41Sopenharmony_ci  def __init__(self, heap, known_name, instance_type):
19441cb0ef41Sopenharmony_ci    HeapObject.__init__(self, heap, None, None)
19451cb0ef41Sopenharmony_ci    self.instance_type = instance_type
19461cb0ef41Sopenharmony_ci    self.known_name = known_name
19471cb0ef41Sopenharmony_ci
19481cb0ef41Sopenharmony_ci  def __str__(self):
19491cb0ef41Sopenharmony_ci    return "<%s>" % self.known_name
19501cb0ef41Sopenharmony_ci
19511cb0ef41Sopenharmony_ci
19521cb0ef41Sopenharmony_ciCOMMENT_RE = re.compile(r"^C (0x[0-9a-fA-F]+) (.*)$")
19531cb0ef41Sopenharmony_ciPAGEADDRESS_RE = re.compile(
19541cb0ef41Sopenharmony_ci    r"^P (mappage|oldpage) (0x[0-9a-fA-F]+)$")
19551cb0ef41Sopenharmony_ci
19561cb0ef41Sopenharmony_ci
19571cb0ef41Sopenharmony_ciclass InspectionInfo(object):
19581cb0ef41Sopenharmony_ci  def __init__(self, minidump_name, reader):
19591cb0ef41Sopenharmony_ci    self.comment_file = minidump_name + ".comments"
19601cb0ef41Sopenharmony_ci    self.address_comments = {}
19611cb0ef41Sopenharmony_ci    self.page_address = {}
19621cb0ef41Sopenharmony_ci    if os.path.exists(self.comment_file):
19631cb0ef41Sopenharmony_ci      with open(self.comment_file, "r") as f:
19641cb0ef41Sopenharmony_ci        lines = f.readlines()
19651cb0ef41Sopenharmony_ci        f.close()
19661cb0ef41Sopenharmony_ci
19671cb0ef41Sopenharmony_ci        for l in lines:
19681cb0ef41Sopenharmony_ci          m = COMMENT_RE.match(l)
19691cb0ef41Sopenharmony_ci          if m:
19701cb0ef41Sopenharmony_ci            self.address_comments[int(m.group(1), 0)] = m.group(2)
19711cb0ef41Sopenharmony_ci          m = PAGEADDRESS_RE.match(l)
19721cb0ef41Sopenharmony_ci          if m:
19731cb0ef41Sopenharmony_ci            self.page_address[m.group(1)] = int(m.group(2), 0)
19741cb0ef41Sopenharmony_ci    self.reader = reader
19751cb0ef41Sopenharmony_ci    self.styles = {}
19761cb0ef41Sopenharmony_ci    self.color_addresses()
19771cb0ef41Sopenharmony_ci    return
19781cb0ef41Sopenharmony_ci
19791cb0ef41Sopenharmony_ci  def get_page_address(self, page_kind):
19801cb0ef41Sopenharmony_ci    return self.page_address.get(page_kind, 0)
19811cb0ef41Sopenharmony_ci
19821cb0ef41Sopenharmony_ci  def save_page_address(self, page_kind, address):
19831cb0ef41Sopenharmony_ci    with open(self.comment_file, "a") as f:
19841cb0ef41Sopenharmony_ci      f.write("P %s 0x%x\n" % (page_kind, address))
19851cb0ef41Sopenharmony_ci      f.close()
19861cb0ef41Sopenharmony_ci
19871cb0ef41Sopenharmony_ci  def color_addresses(self):
19881cb0ef41Sopenharmony_ci    # Color all stack addresses.
19891cb0ef41Sopenharmony_ci    exception_thread = self.reader.thread_map[self.reader.exception.thread_id]
19901cb0ef41Sopenharmony_ci    stack_top = self.reader.ExceptionSP()
19911cb0ef41Sopenharmony_ci    stack_bottom = exception_thread.stack.start + \
19921cb0ef41Sopenharmony_ci        exception_thread.stack.memory.data_size
19931cb0ef41Sopenharmony_ci    frame_pointer = self.reader.ExceptionFP()
19941cb0ef41Sopenharmony_ci    self.styles[frame_pointer] = "frame"
19951cb0ef41Sopenharmony_ci    for slot in range(stack_top, stack_bottom,
19961cb0ef41Sopenharmony_ci                      self.reader.MachinePointerSize()):
19971cb0ef41Sopenharmony_ci      # stack address
19981cb0ef41Sopenharmony_ci      self.styles[slot] = "sa"
19991cb0ef41Sopenharmony_ci    for slot in range(stack_top, stack_bottom,
20001cb0ef41Sopenharmony_ci                      self.reader.MachinePointerSize()):
20011cb0ef41Sopenharmony_ci      maybe_address = self.reader.ReadUIntPtr(slot)
20021cb0ef41Sopenharmony_ci      # stack value
20031cb0ef41Sopenharmony_ci      self.styles[maybe_address] = "sv"
20041cb0ef41Sopenharmony_ci      if slot == frame_pointer:
20051cb0ef41Sopenharmony_ci        self.styles[slot] = "frame"
20061cb0ef41Sopenharmony_ci        frame_pointer = maybe_address
20071cb0ef41Sopenharmony_ci    self.styles[self.reader.ExceptionIP()] = "pc"
20081cb0ef41Sopenharmony_ci
20091cb0ef41Sopenharmony_ci  def get_style_class(self, address):
20101cb0ef41Sopenharmony_ci    return self.styles.get(address, None)
20111cb0ef41Sopenharmony_ci
20121cb0ef41Sopenharmony_ci  def get_style_class_string(self, address):
20131cb0ef41Sopenharmony_ci    style = self.get_style_class(address)
20141cb0ef41Sopenharmony_ci    if style != None:
20151cb0ef41Sopenharmony_ci      return " class=%s " % style
20161cb0ef41Sopenharmony_ci    else:
20171cb0ef41Sopenharmony_ci      return ""
20181cb0ef41Sopenharmony_ci
20191cb0ef41Sopenharmony_ci  def set_comment(self, address, comment):
20201cb0ef41Sopenharmony_ci    self.address_comments[address] = comment
20211cb0ef41Sopenharmony_ci    with open(self.comment_file, "a") as f:
20221cb0ef41Sopenharmony_ci      f.write("C 0x%x %s\n" % (address, comment))
20231cb0ef41Sopenharmony_ci      f.close()
20241cb0ef41Sopenharmony_ci
20251cb0ef41Sopenharmony_ci  def get_comment(self, address):
20261cb0ef41Sopenharmony_ci    return self.address_comments.get(address, "")
20271cb0ef41Sopenharmony_ci
20281cb0ef41Sopenharmony_ci
20291cb0ef41Sopenharmony_ciclass InspectionPadawan(object):
20301cb0ef41Sopenharmony_ci  """The padawan can improve annotations by sensing well-known objects."""
20311cb0ef41Sopenharmony_ci  def __init__(self, reader, heap):
20321cb0ef41Sopenharmony_ci    self.reader = reader
20331cb0ef41Sopenharmony_ci    self.heap = heap
20341cb0ef41Sopenharmony_ci    self.known_first_map_page = 0
20351cb0ef41Sopenharmony_ci    self.known_first_old_page = 0
20361cb0ef41Sopenharmony_ci    self.context = None
20371cb0ef41Sopenharmony_ci
20381cb0ef41Sopenharmony_ci  def __getattr__(self, name):
20391cb0ef41Sopenharmony_ci    """An InspectionPadawan can be used instead of V8Heap, even though
20401cb0ef41Sopenharmony_ci       it does not inherit from V8Heap (aka. mixin)."""
20411cb0ef41Sopenharmony_ci    return getattr(self.heap, name)
20421cb0ef41Sopenharmony_ci
20431cb0ef41Sopenharmony_ci  def GetPageOffset(self, tagged_address):
20441cb0ef41Sopenharmony_ci    return tagged_address & self.heap.PageAlignmentMask()
20451cb0ef41Sopenharmony_ci
20461cb0ef41Sopenharmony_ci  def IsInKnownMapSpace(self, tagged_address):
20471cb0ef41Sopenharmony_ci    page_address = tagged_address & ~self.heap.PageAlignmentMask()
20481cb0ef41Sopenharmony_ci    return page_address == self.known_first_map_page
20491cb0ef41Sopenharmony_ci
20501cb0ef41Sopenharmony_ci  def IsInKnownOldSpace(self, tagged_address):
20511cb0ef41Sopenharmony_ci    page_address = tagged_address & ~self.heap.PageAlignmentMask()
20521cb0ef41Sopenharmony_ci    return page_address == self.known_first_old_page
20531cb0ef41Sopenharmony_ci
20541cb0ef41Sopenharmony_ci  def ContainingKnownOldSpaceName(self, tagged_address):
20551cb0ef41Sopenharmony_ci    page_address = tagged_address & ~self.heap.PageAlignmentMask()
20561cb0ef41Sopenharmony_ci    if page_address == self.known_first_old_page: return "OLD_SPACE"
20571cb0ef41Sopenharmony_ci    return None
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ci  def FrameMarkerName(self, value):
20601cb0ef41Sopenharmony_ci    # The frame marker is Smi-tagged but not Smi encoded and 0 is not a valid
20611cb0ef41Sopenharmony_ci    # frame type.
20621cb0ef41Sopenharmony_ci    value = (value >> 1) - 1
20631cb0ef41Sopenharmony_ci    if 0 <= value < len(FRAME_MARKERS):
20641cb0ef41Sopenharmony_ci      return "Possibly %s frame marker" % FRAME_MARKERS[value]
20651cb0ef41Sopenharmony_ci    return None
20661cb0ef41Sopenharmony_ci
20671cb0ef41Sopenharmony_ci  def IsFrameMarker(self, slot, address):
20681cb0ef41Sopenharmony_ci    if not slot: return False
20691cb0ef41Sopenharmony_ci    # Frame markers only occur directly after a frame pointer and only on the
20701cb0ef41Sopenharmony_ci    # stack.
20711cb0ef41Sopenharmony_ci    if not self.reader.IsExceptionStackAddress(slot): return False
20721cb0ef41Sopenharmony_ci    next_slot = slot + self.reader.MachinePointerSize()
20731cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(next_slot): return False
20741cb0ef41Sopenharmony_ci    next_address = self.reader.ReadUIntPtr(next_slot)
20751cb0ef41Sopenharmony_ci    return self.reader.IsExceptionStackAddress(next_address)
20761cb0ef41Sopenharmony_ci
20771cb0ef41Sopenharmony_ci  def FormatSmi(self, address):
20781cb0ef41Sopenharmony_ci    value = self.heap.SmiUntag(address)
20791cb0ef41Sopenharmony_ci    # On 32-bit systems almost everything looks like a Smi.
20801cb0ef41Sopenharmony_ci    if not self.reader.Is64() or value == 0: return None
20811cb0ef41Sopenharmony_ci    return "Smi(%d)" % value
20821cb0ef41Sopenharmony_ci
20831cb0ef41Sopenharmony_ci  def SenseObject(self, address, slot=None):
20841cb0ef41Sopenharmony_ci    if self.IsFrameMarker(slot, address):
20851cb0ef41Sopenharmony_ci      return self.FrameMarkerName(address)
20861cb0ef41Sopenharmony_ci    if self.heap.IsSmi(address):
20871cb0ef41Sopenharmony_ci      return self.FormatSmi(address)
20881cb0ef41Sopenharmony_ci    if not self.heap.IsTaggedAddress(address): return None
20891cb0ef41Sopenharmony_ci    tagged_address = address
20901cb0ef41Sopenharmony_ci    if self.IsInKnownOldSpace(tagged_address):
20911cb0ef41Sopenharmony_ci      offset = self.GetPageOffset(tagged_address)
20921cb0ef41Sopenharmony_ci      lookup_key = (self.ContainingKnownOldSpaceName(tagged_address), offset)
20931cb0ef41Sopenharmony_ci      known_obj_name = KNOWN_OBJECTS.get(lookup_key)
20941cb0ef41Sopenharmony_ci      if known_obj_name:
20951cb0ef41Sopenharmony_ci        return KnownObject(self, known_obj_name)
20961cb0ef41Sopenharmony_ci    if self.IsInKnownMapSpace(tagged_address):
20971cb0ef41Sopenharmony_ci      known_map = self.SenseMap(tagged_address)
20981cb0ef41Sopenharmony_ci      if known_map:
20991cb0ef41Sopenharmony_ci        return known_map
21001cb0ef41Sopenharmony_ci    found_obj = self.heap.FindObject(tagged_address)
21011cb0ef41Sopenharmony_ci    if found_obj: return found_obj
21021cb0ef41Sopenharmony_ci    address = tagged_address - 1
21031cb0ef41Sopenharmony_ci    if self.reader.IsValidAddress(address):
21041cb0ef41Sopenharmony_ci      map_tagged_address = self.reader.ReadTagged(address)
21051cb0ef41Sopenharmony_ci      map = self.SenseMap(map_tagged_address)
21061cb0ef41Sopenharmony_ci      if map is None: return None
21071cb0ef41Sopenharmony_ci      instance_type_name = INSTANCE_TYPES.get(map.instance_type)
21081cb0ef41Sopenharmony_ci      if instance_type_name is None: return None
21091cb0ef41Sopenharmony_ci      cls = V8Heap.CLASS_MAP.get(instance_type_name, HeapObject)
21101cb0ef41Sopenharmony_ci      return cls(self, map, address)
21111cb0ef41Sopenharmony_ci    return None
21121cb0ef41Sopenharmony_ci
21131cb0ef41Sopenharmony_ci  def SenseMap(self, tagged_address):
21141cb0ef41Sopenharmony_ci    if self.IsInKnownMapSpace(tagged_address):
21151cb0ef41Sopenharmony_ci      offset = self.GetPageOffset(tagged_address)
21161cb0ef41Sopenharmony_ci      lookup_key = ("MAP_SPACE", offset)
21171cb0ef41Sopenharmony_ci      known_map_info = KNOWN_MAPS.get(lookup_key)
21181cb0ef41Sopenharmony_ci      if known_map_info:
21191cb0ef41Sopenharmony_ci        known_map_type, known_map_name = known_map_info
21201cb0ef41Sopenharmony_ci        return KnownMap(self, known_map_name, known_map_type)
21211cb0ef41Sopenharmony_ci    found_map = self.heap.FindMap(tagged_address)
21221cb0ef41Sopenharmony_ci    if found_map: return found_map
21231cb0ef41Sopenharmony_ci    return None
21241cb0ef41Sopenharmony_ci
21251cb0ef41Sopenharmony_ci  def FindObjectOrSmi(self, tagged_address):
21261cb0ef41Sopenharmony_ci    """When used as a mixin in place of V8Heap."""
21271cb0ef41Sopenharmony_ci    found_obj = self.SenseObject(tagged_address)
21281cb0ef41Sopenharmony_ci    if found_obj: return found_obj
21291cb0ef41Sopenharmony_ci    if self.IsSmi(tagged_address):
21301cb0ef41Sopenharmony_ci      return self.FormatSmi(tagged_address)
21311cb0ef41Sopenharmony_ci    else:
21321cb0ef41Sopenharmony_ci      return "Unknown(%s)" % self.reader.FormatIntPtr(tagged_address)
21331cb0ef41Sopenharmony_ci
21341cb0ef41Sopenharmony_ci  def FindObject(self, tagged_address):
21351cb0ef41Sopenharmony_ci    """When used as a mixin in place of V8Heap."""
21361cb0ef41Sopenharmony_ci    raise NotImplementedError
21371cb0ef41Sopenharmony_ci
21381cb0ef41Sopenharmony_ci  def FindMap(self, tagged_address):
21391cb0ef41Sopenharmony_ci    """When used as a mixin in place of V8Heap."""
21401cb0ef41Sopenharmony_ci    raise NotImplementedError
21411cb0ef41Sopenharmony_ci
21421cb0ef41Sopenharmony_ci  def PrintKnowledge(self):
21431cb0ef41Sopenharmony_ci    print("  known_first_map_page = %s\n"\
21441cb0ef41Sopenharmony_ci          "  known_first_old_page = %s" % (
21451cb0ef41Sopenharmony_ci          self.reader.FormatIntPtr(self.known_first_map_page),
21461cb0ef41Sopenharmony_ci          self.reader.FormatIntPtr(self.known_first_old_page)))
21471cb0ef41Sopenharmony_ci
21481cb0ef41Sopenharmony_ci  def FindFirstAsciiString(self, start, end=None, min_length=32):
21491cb0ef41Sopenharmony_ci    """ Walk the memory until we find a large string """
21501cb0ef41Sopenharmony_ci    if not end: end = start + 64
21511cb0ef41Sopenharmony_ci    for slot in range(start, end):
21521cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(slot): break
21531cb0ef41Sopenharmony_ci      message = self.reader.ReadAsciiString(slot)
21541cb0ef41Sopenharmony_ci      if len(message) > min_length:
21551cb0ef41Sopenharmony_ci        return (slot, message)
21561cb0ef41Sopenharmony_ci    return (None,None)
21571cb0ef41Sopenharmony_ci
21581cb0ef41Sopenharmony_ci  def PrintStackTraceMessage(self, start=None, print_message=True):
21591cb0ef41Sopenharmony_ci    """
21601cb0ef41Sopenharmony_ci    Try to print a possible message from PushStackTraceAndDie.
21611cb0ef41Sopenharmony_ci    Returns the first address where the normal stack starts again.
21621cb0ef41Sopenharmony_ci    """
21631cb0ef41Sopenharmony_ci    # Only look at the first 1k words on the stack
21641cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
21651cb0ef41Sopenharmony_ci    if start is None: start = self.reader.ExceptionSP()
21661cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(start): return start
21671cb0ef41Sopenharmony_ci    end = start + ptr_size * 1024 * 4
21681cb0ef41Sopenharmony_ci    magic1 = None
21691cb0ef41Sopenharmony_ci    for slot in range(start, end, ptr_size):
21701cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(slot + ptr_size): break
21711cb0ef41Sopenharmony_ci      magic1 = self.reader.ReadUIntPtr(slot)
21721cb0ef41Sopenharmony_ci      magic2 = self.reader.ReadUIntPtr(slot + ptr_size)
21731cb0ef41Sopenharmony_ci      pair = (magic1 & 0xFFFFFFFF, magic2 & 0xFFFFFFFF)
21741cb0ef41Sopenharmony_ci      if pair in MAGIC_MARKER_PAIRS:
21751cb0ef41Sopenharmony_ci        return self.TryExtractOldStyleStackTrace(slot, start, end,
21761cb0ef41Sopenharmony_ci                                                 print_message)
21771cb0ef41Sopenharmony_ci      if pair[0] == STACK_TRACE_MARKER:
21781cb0ef41Sopenharmony_ci        return self.TryExtractStackTrace(slot, start, end, print_message)
21791cb0ef41Sopenharmony_ci      elif pair[0] == ERROR_MESSAGE_MARKER:
21801cb0ef41Sopenharmony_ci        return self.TryExtractErrorMessage(slot, start, end, print_message)
21811cb0ef41Sopenharmony_ci    # Simple fallback in case not stack trace object was found
21821cb0ef41Sopenharmony_ci    return self.TryExtractOldStyleStackTrace(0, start, end,
21831cb0ef41Sopenharmony_ci                                             print_message)
21841cb0ef41Sopenharmony_ci
21851cb0ef41Sopenharmony_ci  def TryExtractStackTrace(self, slot, start, end, print_message):
21861cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
21871cb0ef41Sopenharmony_ci    assert self.reader.ReadUIntPtr(slot) & 0xFFFFFFFF == STACK_TRACE_MARKER
21881cb0ef41Sopenharmony_ci    end_marker = STACK_TRACE_MARKER + 1;
21891cb0ef41Sopenharmony_ci    header_size = 10
21901cb0ef41Sopenharmony_ci    # Look for the end marker after the fields and the message buffer.
21911cb0ef41Sopenharmony_ci    end_search = start + (32 * 1024) + (header_size * ptr_size);
21921cb0ef41Sopenharmony_ci    end_slot = self.FindPtr(end_marker, end_search, end_search + ptr_size * 512)
21931cb0ef41Sopenharmony_ci    if not end_slot: return start
21941cb0ef41Sopenharmony_ci    print("Stack Message (start=%s):" % self.heap.FormatIntPtr(slot))
21951cb0ef41Sopenharmony_ci    slot += ptr_size
21961cb0ef41Sopenharmony_ci    for name in ("isolate","ptr1", "ptr2", "ptr3", "ptr4", "codeObject1",
21971cb0ef41Sopenharmony_ci                 "codeObject2", "codeObject3", "codeObject4"):
21981cb0ef41Sopenharmony_ci      value = self.reader.ReadUIntPtr(slot)
21991cb0ef41Sopenharmony_ci      print(" %s: %s" % (name.rjust(14), self.heap.FormatIntPtr(value)))
22001cb0ef41Sopenharmony_ci      slot += ptr_size
22011cb0ef41Sopenharmony_ci    print("  message start: %s" % self.heap.FormatIntPtr(slot))
22021cb0ef41Sopenharmony_ci    stack_start = end_slot + ptr_size
22031cb0ef41Sopenharmony_ci    print("  stack_start:   %s" % self.heap.FormatIntPtr(stack_start))
22041cb0ef41Sopenharmony_ci    (message_start, message) = self.FindFirstAsciiString(slot)
22051cb0ef41Sopenharmony_ci    self.FormatStackTrace(message, print_message)
22061cb0ef41Sopenharmony_ci    return stack_start
22071cb0ef41Sopenharmony_ci
22081cb0ef41Sopenharmony_ci  def FindPtr(self, expected_value, start, end):
22091cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
22101cb0ef41Sopenharmony_ci    for slot in range(start, end, ptr_size):
22111cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(slot): return None
22121cb0ef41Sopenharmony_ci      value = self.reader.ReadUIntPtr(slot)
22131cb0ef41Sopenharmony_ci      if value == expected_value: return slot
22141cb0ef41Sopenharmony_ci    return None
22151cb0ef41Sopenharmony_ci
22161cb0ef41Sopenharmony_ci  def TryExtractErrorMessage(self, slot, start, end, print_message):
22171cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
22181cb0ef41Sopenharmony_ci    end_marker = ERROR_MESSAGE_MARKER + 1;
22191cb0ef41Sopenharmony_ci    header_size = 1
22201cb0ef41Sopenharmony_ci    end_search = start + 1024 + (header_size * ptr_size);
22211cb0ef41Sopenharmony_ci    end_slot = self.FindPtr(end_marker, end_search, end_search + ptr_size * 512)
22221cb0ef41Sopenharmony_ci    if not end_slot: return start
22231cb0ef41Sopenharmony_ci    print("Error Message (start=%s):" % self.heap.FormatIntPtr(slot))
22241cb0ef41Sopenharmony_ci    slot += ptr_size
22251cb0ef41Sopenharmony_ci    (message_start, message) = self.FindFirstAsciiString(slot)
22261cb0ef41Sopenharmony_ci    self.FormatStackTrace(message, print_message)
22271cb0ef41Sopenharmony_ci    stack_start = end_slot + ptr_size
22281cb0ef41Sopenharmony_ci    return stack_start
22291cb0ef41Sopenharmony_ci
22301cb0ef41Sopenharmony_ci  def TryExtractOldStyleStackTrace(self, message_slot, start, end,
22311cb0ef41Sopenharmony_ci                                   print_message):
22321cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
22331cb0ef41Sopenharmony_ci    if message_slot == 0:
22341cb0ef41Sopenharmony_ci      """
22351cb0ef41Sopenharmony_ci      On Mac we don't always get proper magic markers, so just try printing
22361cb0ef41Sopenharmony_ci      the first long ascii string found on the stack.
22371cb0ef41Sopenharmony_ci      """
22381cb0ef41Sopenharmony_ci      magic1 = None
22391cb0ef41Sopenharmony_ci      magic2 = None
22401cb0ef41Sopenharmony_ci      message_start, message = self.FindFirstAsciiString(start, end, 128)
22411cb0ef41Sopenharmony_ci      if message_start is None: return start
22421cb0ef41Sopenharmony_ci    else:
22431cb0ef41Sopenharmony_ci      message_start = self.reader.ReadUIntPtr(message_slot + ptr_size * 4)
22441cb0ef41Sopenharmony_ci      message = self.reader.ReadAsciiString(message_start)
22451cb0ef41Sopenharmony_ci    stack_start = message_start + len(message) + 1
22461cb0ef41Sopenharmony_ci    # Make sure the address is word aligned
22471cb0ef41Sopenharmony_ci    stack_start =  stack_start - (stack_start % ptr_size)
22481cb0ef41Sopenharmony_ci    if magic1 is None:
22491cb0ef41Sopenharmony_ci      print("Stack Message:")
22501cb0ef41Sopenharmony_ci      print("  message start: %s" % self.heap.FormatIntPtr(message_start))
22511cb0ef41Sopenharmony_ci      print("  stack_start:   %s" % self.heap.FormatIntPtr(stack_start ))
22521cb0ef41Sopenharmony_ci    else:
22531cb0ef41Sopenharmony_ci      ptr1 = self.reader.ReadUIntPtr(slot + ptr_size * 2)
22541cb0ef41Sopenharmony_ci      ptr2 = self.reader.ReadUIntPtr(slot + ptr_size * 3)
22551cb0ef41Sopenharmony_ci      print("Stack Message:")
22561cb0ef41Sopenharmony_ci      print("  magic1:        %s" % self.heap.FormatIntPtr(magic1))
22571cb0ef41Sopenharmony_ci      print("  magic2:        %s" % self.heap.FormatIntPtr(magic2))
22581cb0ef41Sopenharmony_ci      print("  ptr1:          %s" % self.heap.FormatIntPtr(ptr1))
22591cb0ef41Sopenharmony_ci      print("  ptr2:          %s" % self.heap.FormatIntPtr(ptr2))
22601cb0ef41Sopenharmony_ci      print("  message start: %s" % self.heap.FormatIntPtr(message_start))
22611cb0ef41Sopenharmony_ci      print("  stack_start:   %s" % self.heap.FormatIntPtr(stack_start ))
22621cb0ef41Sopenharmony_ci      print("")
22631cb0ef41Sopenharmony_ci    self.FormatStackTrace(message, print_message)
22641cb0ef41Sopenharmony_ci    return stack_start
22651cb0ef41Sopenharmony_ci
22661cb0ef41Sopenharmony_ci  def FormatStackTrace(self, message, print_message):
22671cb0ef41Sopenharmony_ci    if not print_message:
22681cb0ef41Sopenharmony_ci      print("  Use `dsa` to print the message with annotated addresses.")
22691cb0ef41Sopenharmony_ci      print("")
22701cb0ef41Sopenharmony_ci      return
22711cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
22721cb0ef41Sopenharmony_ci    # Annotate all addresses in the dumped message
22731cb0ef41Sopenharmony_ci    prog = re.compile("[0-9a-fA-F]{%s}" % ptr_size*2)
22741cb0ef41Sopenharmony_ci    addresses = list(set(prog.findall(message)))
22751cb0ef41Sopenharmony_ci    for i in range(len(addresses)):
22761cb0ef41Sopenharmony_ci      address_org = addresses[i]
22771cb0ef41Sopenharmony_ci      address = self.heap.FormatIntPtr(int(address_org, 16))
22781cb0ef41Sopenharmony_ci      if address_org != address:
22791cb0ef41Sopenharmony_ci        message = message.replace(address_org, address)
22801cb0ef41Sopenharmony_ci    print("Message:")
22811cb0ef41Sopenharmony_ci    print("="*80)
22821cb0ef41Sopenharmony_ci    print(message)
22831cb0ef41Sopenharmony_ci    print("="*80)
22841cb0ef41Sopenharmony_ci    print("")
22851cb0ef41Sopenharmony_ci
22861cb0ef41Sopenharmony_ci
22871cb0ef41Sopenharmony_ci  def TryInferFramePointer(self, slot, address):
22881cb0ef41Sopenharmony_ci    """ Assume we have a framepointer if we find 4 consecutive links """
22891cb0ef41Sopenharmony_ci    for i in range(0, 4):
22901cb0ef41Sopenharmony_ci      if not self.reader.IsExceptionStackAddress(address): return 0
22911cb0ef41Sopenharmony_ci      next_address = self.reader.ReadUIntPtr(address)
22921cb0ef41Sopenharmony_ci      if next_address == address: return 0
22931cb0ef41Sopenharmony_ci      address = next_address
22941cb0ef41Sopenharmony_ci    return slot
22951cb0ef41Sopenharmony_ci
22961cb0ef41Sopenharmony_ci  def TryInferContext(self, address):
22971cb0ef41Sopenharmony_ci    if self.context: return
22981cb0ef41Sopenharmony_ci    ptr_size = self.reader.MachinePointerSize()
22991cb0ef41Sopenharmony_ci    possible_context = dict()
23001cb0ef41Sopenharmony_ci    count = 0
23011cb0ef41Sopenharmony_ci    while self.reader.IsExceptionStackAddress(address):
23021cb0ef41Sopenharmony_ci      prev_addr = self.reader.ReadUIntPtr(address-ptr_size)
23031cb0ef41Sopenharmony_ci      if self.heap.IsTaggedObjectAddress(prev_addr):
23041cb0ef41Sopenharmony_ci        if prev_addr in possible_context:
23051cb0ef41Sopenharmony_ci          possible_context[prev_addr] += 1
23061cb0ef41Sopenharmony_ci        else:
23071cb0ef41Sopenharmony_ci          possible_context[prev_addr] = 1
23081cb0ef41Sopenharmony_ci      address = self.reader.ReadUIntPtr(address)
23091cb0ef41Sopenharmony_ci      count += 1
23101cb0ef41Sopenharmony_ci    if count <= 5 or len(possible_context) == 0: return
23111cb0ef41Sopenharmony_ci    # Find entry with highest count
23121cb0ef41Sopenharmony_ci    possible_context = list(possible_context.items())
23131cb0ef41Sopenharmony_ci    possible_context.sort(key=lambda pair: pair[1])
23141cb0ef41Sopenharmony_ci    address,count = possible_context[-1]
23151cb0ef41Sopenharmony_ci    if count <= 4: return
23161cb0ef41Sopenharmony_ci    self.context = address
23171cb0ef41Sopenharmony_ci
23181cb0ef41Sopenharmony_ci  def InterpretMemory(self, start, end):
23191cb0ef41Sopenharmony_ci    # On 64 bit we omit frame pointers, so we have to do some more guesswork.
23201cb0ef41Sopenharmony_ci    frame_pointer = 0
23211cb0ef41Sopenharmony_ci    if not self.reader.Is64():
23221cb0ef41Sopenharmony_ci      frame_pointer = self.reader.ExceptionFP()
23231cb0ef41Sopenharmony_ci      # Follow the framepointer into the address range
23241cb0ef41Sopenharmony_ci      while frame_pointer and frame_pointer < start:
23251cb0ef41Sopenharmony_ci        frame_pointer = self.reader.ReadUIntPtr(frame_pointer)
23261cb0ef41Sopenharmony_ci        if not self.reader.IsExceptionStackAddress(frame_pointer) or \
23271cb0ef41Sopenharmony_ci            not frame_pointer:
23281cb0ef41Sopenharmony_ci          frame_pointer = 0
23291cb0ef41Sopenharmony_ci          break
23301cb0ef41Sopenharmony_ci    in_oom_dump_area  = False
23311cb0ef41Sopenharmony_ci    is_stack = self.reader.IsExceptionStackAddress(start)
23321cb0ef41Sopenharmony_ci    free_space_end = 0
23331cb0ef41Sopenharmony_ci    ptr_size = self.reader.TaggedPointerSize()
23341cb0ef41Sopenharmony_ci
23351cb0ef41Sopenharmony_ci    for slot in range(start, end, ptr_size):
23361cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(slot):
23371cb0ef41Sopenharmony_ci        print("%s: Address is not contained within the minidump!" % slot)
23381cb0ef41Sopenharmony_ci        return
23391cb0ef41Sopenharmony_ci      maybe_address = self.reader.ReadUIntPtr(slot)
23401cb0ef41Sopenharmony_ci      address_info = []
23411cb0ef41Sopenharmony_ci      # Mark continuous free space objects
23421cb0ef41Sopenharmony_ci      if slot == free_space_end:
23431cb0ef41Sopenharmony_ci        address_info.append("+")
23441cb0ef41Sopenharmony_ci      elif slot <= free_space_end:
23451cb0ef41Sopenharmony_ci        address_info.append("|")
23461cb0ef41Sopenharmony_ci      else:
23471cb0ef41Sopenharmony_ci        free_space_end = 0
23481cb0ef41Sopenharmony_ci
23491cb0ef41Sopenharmony_ci      heap_object = self.SenseObject(maybe_address, slot)
23501cb0ef41Sopenharmony_ci      if heap_object:
23511cb0ef41Sopenharmony_ci        # Detect Free-space ranges
23521cb0ef41Sopenharmony_ci        if isinstance(heap_object, KnownMap) and \
23531cb0ef41Sopenharmony_ci            heap_object.known_name == "FreeSpaceMap":
23541cb0ef41Sopenharmony_ci          # The free-space length is is stored as a Smi in the next slot.
23551cb0ef41Sopenharmony_ci          length = self.reader.ReadTagged(slot + ptr_size)
23561cb0ef41Sopenharmony_ci          if self.heap.IsSmi(length):
23571cb0ef41Sopenharmony_ci            length = self.heap.SmiUntag(length)
23581cb0ef41Sopenharmony_ci            free_space_end = slot + length - ptr_size
23591cb0ef41Sopenharmony_ci        address_info.append(str(heap_object))
23601cb0ef41Sopenharmony_ci      relative_offset = self.heap.RelativeOffset(slot, maybe_address)
23611cb0ef41Sopenharmony_ci      if relative_offset:
23621cb0ef41Sopenharmony_ci        address_info.append(relative_offset)
23631cb0ef41Sopenharmony_ci      if maybe_address == self.context:
23641cb0ef41Sopenharmony_ci        address_info.append("CONTEXT")
23651cb0ef41Sopenharmony_ci
23661cb0ef41Sopenharmony_ci      maybe_address_contents = None
23671cb0ef41Sopenharmony_ci      if is_stack:
23681cb0ef41Sopenharmony_ci        if self.reader.IsExceptionStackAddress(maybe_address):
23691cb0ef41Sopenharmony_ci          maybe_address_contents = \
23701cb0ef41Sopenharmony_ci              self.reader.ReadUIntPtr(maybe_address) & 0xFFFFFFFF
23711cb0ef41Sopenharmony_ci          if maybe_address_contents == 0xdecade00:
23721cb0ef41Sopenharmony_ci            in_oom_dump_area = True
23731cb0ef41Sopenharmony_ci          if frame_pointer == 0:
23741cb0ef41Sopenharmony_ci            frame_pointer = self.TryInferFramePointer(slot, maybe_address)
23751cb0ef41Sopenharmony_ci            if frame_pointer != 0:
23761cb0ef41Sopenharmony_ci              self.TryInferContext(slot)
23771cb0ef41Sopenharmony_ci        maybe_symbol = self.reader.FindSymbol(maybe_address)
23781cb0ef41Sopenharmony_ci        if in_oom_dump_area:
23791cb0ef41Sopenharmony_ci          if maybe_address_contents == 0xdecade00:
23801cb0ef41Sopenharmony_ci            address_info = ["<==== HeapStats start marker"]
23811cb0ef41Sopenharmony_ci          elif maybe_address_contents == 0xdecade01:
23821cb0ef41Sopenharmony_ci            address_info = ["<==== HeapStats end marker"]
23831cb0ef41Sopenharmony_ci          elif maybe_address_contents is not None:
23841cb0ef41Sopenharmony_ci            address_info = [" %d (%d Mbytes)" % (maybe_address_contents,
23851cb0ef41Sopenharmony_ci                                                 maybe_address_contents >> 20)]
23861cb0ef41Sopenharmony_ci        if slot == frame_pointer:
23871cb0ef41Sopenharmony_ci          if not self.reader.IsExceptionStackAddress(maybe_address):
23881cb0ef41Sopenharmony_ci            address_info.append("<==== BAD frame pointer")
23891cb0ef41Sopenharmony_ci            frame_pointer = 0
23901cb0ef41Sopenharmony_ci          else:
23911cb0ef41Sopenharmony_ci            address_info.append("<==== Frame pointer")
23921cb0ef41Sopenharmony_ci          frame_pointer = maybe_address
23931cb0ef41Sopenharmony_ci      address_type_marker = self.heap.AddressTypeMarker(maybe_address)
23941cb0ef41Sopenharmony_ci      string_value = self.reader.ReadAsciiPtr(slot)
23951cb0ef41Sopenharmony_ci      print("%s: %s %s %s %s" % (self.reader.FormatIntPtr(slot),
23961cb0ef41Sopenharmony_ci                           self.reader.FormatIntPtr(maybe_address),
23971cb0ef41Sopenharmony_ci                           address_type_marker,
23981cb0ef41Sopenharmony_ci                           string_value,
23991cb0ef41Sopenharmony_ci                           ' | '.join(address_info)))
24001cb0ef41Sopenharmony_ci      if maybe_address_contents == 0xdecade01:
24011cb0ef41Sopenharmony_ci        in_oom_dump_area = False
24021cb0ef41Sopenharmony_ci      heap_object = self.heap.FindObject(maybe_address)
24031cb0ef41Sopenharmony_ci      if heap_object:
24041cb0ef41Sopenharmony_ci        heap_object.Print(Printer())
24051cb0ef41Sopenharmony_ci        print("")
24061cb0ef41Sopenharmony_ci
24071cb0ef41Sopenharmony_ciWEB_HEADER = """
24081cb0ef41Sopenharmony_ci<!DOCTYPE html>
24091cb0ef41Sopenharmony_ci<html>
24101cb0ef41Sopenharmony_ci<head>
24111cb0ef41Sopenharmony_ci<meta content="text/html; charset=utf-8" http-equiv="content-type">
24121cb0ef41Sopenharmony_ci<style media="screen" type="text/css">
24131cb0ef41Sopenharmony_ci
24141cb0ef41Sopenharmony_ci.code {
24151cb0ef41Sopenharmony_ci  font-family: monospace;
24161cb0ef41Sopenharmony_ci}
24171cb0ef41Sopenharmony_ci
24181cb0ef41Sopenharmony_ci.dmptable {
24191cb0ef41Sopenharmony_ci  border-collapse : collapse;
24201cb0ef41Sopenharmony_ci  border-spacing : 0px;
24211cb0ef41Sopenharmony_ci  table-layout: fixed;
24221cb0ef41Sopenharmony_ci}
24231cb0ef41Sopenharmony_ci
24241cb0ef41Sopenharmony_ci.codedump {
24251cb0ef41Sopenharmony_ci  border-collapse : collapse;
24261cb0ef41Sopenharmony_ci  border-spacing : 0px;
24271cb0ef41Sopenharmony_ci  table-layout: fixed;
24281cb0ef41Sopenharmony_ci}
24291cb0ef41Sopenharmony_ci
24301cb0ef41Sopenharmony_ci.addrcomments {
24311cb0ef41Sopenharmony_ci  border : 0px;
24321cb0ef41Sopenharmony_ci}
24331cb0ef41Sopenharmony_ci
24341cb0ef41Sopenharmony_ci.register {
24351cb0ef41Sopenharmony_ci  padding-right : 1em;
24361cb0ef41Sopenharmony_ci}
24371cb0ef41Sopenharmony_ci
24381cb0ef41Sopenharmony_ci.header {
24391cb0ef41Sopenharmony_ci  clear : both;
24401cb0ef41Sopenharmony_ci}
24411cb0ef41Sopenharmony_ci
24421cb0ef41Sopenharmony_ci.header .navigation {
24431cb0ef41Sopenharmony_ci  float : left;
24441cb0ef41Sopenharmony_ci}
24451cb0ef41Sopenharmony_ci
24461cb0ef41Sopenharmony_ci.header .dumpname {
24471cb0ef41Sopenharmony_ci  float : right;
24481cb0ef41Sopenharmony_ci}
24491cb0ef41Sopenharmony_ci
24501cb0ef41Sopenharmony_citr.highlight-line {
24511cb0ef41Sopenharmony_ci  background-color : yellow;
24521cb0ef41Sopenharmony_ci}
24531cb0ef41Sopenharmony_ci
24541cb0ef41Sopenharmony_ci.highlight {
24551cb0ef41Sopenharmony_ci  background-color : magenta;
24561cb0ef41Sopenharmony_ci}
24571cb0ef41Sopenharmony_ci
24581cb0ef41Sopenharmony_citr.inexact-highlight-line {
24591cb0ef41Sopenharmony_ci  background-color : pink;
24601cb0ef41Sopenharmony_ci}
24611cb0ef41Sopenharmony_ci
24621cb0ef41Sopenharmony_ciinput {
24631cb0ef41Sopenharmony_ci  background-color: inherit;
24641cb0ef41Sopenharmony_ci  border: 1px solid LightGray;
24651cb0ef41Sopenharmony_ci}
24661cb0ef41Sopenharmony_ci
24671cb0ef41Sopenharmony_ci.dumpcomments {
24681cb0ef41Sopenharmony_ci  border : 1px solid LightGray;
24691cb0ef41Sopenharmony_ci  width : 32em;
24701cb0ef41Sopenharmony_ci}
24711cb0ef41Sopenharmony_ci
24721cb0ef41Sopenharmony_ci.regions td {
24731cb0ef41Sopenharmony_ci  padding:0 15px 0 15px;
24741cb0ef41Sopenharmony_ci}
24751cb0ef41Sopenharmony_ci
24761cb0ef41Sopenharmony_ci.stackframe td {
24771cb0ef41Sopenharmony_ci  background-color : cyan;
24781cb0ef41Sopenharmony_ci}
24791cb0ef41Sopenharmony_ci
24801cb0ef41Sopenharmony_ci.stackaddress, .sa {
24811cb0ef41Sopenharmony_ci  background-color : LightGray;
24821cb0ef41Sopenharmony_ci}
24831cb0ef41Sopenharmony_ci
24841cb0ef41Sopenharmony_ci.stackval, .sv {
24851cb0ef41Sopenharmony_ci  background-color : LightCyan;
24861cb0ef41Sopenharmony_ci}
24871cb0ef41Sopenharmony_ci
24881cb0ef41Sopenharmony_ci.frame {
24891cb0ef41Sopenharmony_ci  background-color : cyan;
24901cb0ef41Sopenharmony_ci}
24911cb0ef41Sopenharmony_ci
24921cb0ef41Sopenharmony_ci.commentinput, .ci {
24931cb0ef41Sopenharmony_ci  width : 20em;
24941cb0ef41Sopenharmony_ci}
24951cb0ef41Sopenharmony_ci
24961cb0ef41Sopenharmony_ci/* a.nodump */
24971cb0ef41Sopenharmony_cia.nd:visited {
24981cb0ef41Sopenharmony_ci  color : black;
24991cb0ef41Sopenharmony_ci  text-decoration : none;
25001cb0ef41Sopenharmony_ci}
25011cb0ef41Sopenharmony_ci
25021cb0ef41Sopenharmony_cia.nd:link {
25031cb0ef41Sopenharmony_ci  color : black;
25041cb0ef41Sopenharmony_ci  text-decoration : none;
25051cb0ef41Sopenharmony_ci}
25061cb0ef41Sopenharmony_ci
25071cb0ef41Sopenharmony_cia:visited {
25081cb0ef41Sopenharmony_ci  color : blueviolet;
25091cb0ef41Sopenharmony_ci}
25101cb0ef41Sopenharmony_ci
25111cb0ef41Sopenharmony_cia:link {
25121cb0ef41Sopenharmony_ci  color : blue;
25131cb0ef41Sopenharmony_ci}
25141cb0ef41Sopenharmony_ci
25151cb0ef41Sopenharmony_ci.disasmcomment {
25161cb0ef41Sopenharmony_ci  color : DarkGreen;
25171cb0ef41Sopenharmony_ci}
25181cb0ef41Sopenharmony_ci
25191cb0ef41Sopenharmony_ci</style>
25201cb0ef41Sopenharmony_ci
25211cb0ef41Sopenharmony_ci<script type="application/javascript">
25221cb0ef41Sopenharmony_ci
25231cb0ef41Sopenharmony_civar address_str = "address-";
25241cb0ef41Sopenharmony_civar address_len = address_str.length;
25251cb0ef41Sopenharmony_ci
25261cb0ef41Sopenharmony_cifunction comment() {
25271cb0ef41Sopenharmony_ci  var s = event.srcElement.id;
25281cb0ef41Sopenharmony_ci  var index = s.indexOf(address_str);
25291cb0ef41Sopenharmony_ci  if (index >= 0) {
25301cb0ef41Sopenharmony_ci    send_comment(s.substring(index + address_len), event.srcElement.value);
25311cb0ef41Sopenharmony_ci  }
25321cb0ef41Sopenharmony_ci}
25331cb0ef41Sopenharmony_civar c = comment;
25341cb0ef41Sopenharmony_ci
25351cb0ef41Sopenharmony_cifunction send_comment(address, comment) {
25361cb0ef41Sopenharmony_ci  xmlhttp = new XMLHttpRequest();
25371cb0ef41Sopenharmony_ci  address = encodeURIComponent(address)
25381cb0ef41Sopenharmony_ci  comment = encodeURIComponent(comment)
25391cb0ef41Sopenharmony_ci  xmlhttp.open("GET",
25401cb0ef41Sopenharmony_ci      "setcomment?%(query_dump)s&address=" + address +
25411cb0ef41Sopenharmony_ci      "&comment=" + comment, true);
25421cb0ef41Sopenharmony_ci  xmlhttp.send();
25431cb0ef41Sopenharmony_ci}
25441cb0ef41Sopenharmony_ci
25451cb0ef41Sopenharmony_civar dump_str = "dump-";
25461cb0ef41Sopenharmony_civar dump_len = dump_str.length;
25471cb0ef41Sopenharmony_ci
25481cb0ef41Sopenharmony_cifunction dump_comment() {
25491cb0ef41Sopenharmony_ci  var s = event.srcElement.id;
25501cb0ef41Sopenharmony_ci  var index = s.indexOf(dump_str);
25511cb0ef41Sopenharmony_ci  if (index >= 0) {
25521cb0ef41Sopenharmony_ci    send_dump_desc(s.substring(index + dump_len), event.srcElement.value);
25531cb0ef41Sopenharmony_ci  }
25541cb0ef41Sopenharmony_ci}
25551cb0ef41Sopenharmony_ci
25561cb0ef41Sopenharmony_cifunction send_dump_desc(name, desc) {
25571cb0ef41Sopenharmony_ci  xmlhttp = new XMLHttpRequest();
25581cb0ef41Sopenharmony_ci  name = encodeURIComponent(name)
25591cb0ef41Sopenharmony_ci  desc = encodeURIComponent(desc)
25601cb0ef41Sopenharmony_ci  xmlhttp.open("GET",
25611cb0ef41Sopenharmony_ci      "setdumpdesc?dump=" + name +
25621cb0ef41Sopenharmony_ci      "&description=" + desc, true);
25631cb0ef41Sopenharmony_ci  xmlhttp.send();
25641cb0ef41Sopenharmony_ci}
25651cb0ef41Sopenharmony_ci
25661cb0ef41Sopenharmony_cifunction onpage(kind, address) {
25671cb0ef41Sopenharmony_ci  xmlhttp = new XMLHttpRequest();
25681cb0ef41Sopenharmony_ci  kind = encodeURIComponent(kind)
25691cb0ef41Sopenharmony_ci  address = encodeURIComponent(address)
25701cb0ef41Sopenharmony_ci  xmlhttp.onreadystatechange = function() {
25711cb0ef41Sopenharmony_ci    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
25721cb0ef41Sopenharmony_ci      location.reload(true)
25731cb0ef41Sopenharmony_ci    }
25741cb0ef41Sopenharmony_ci  };
25751cb0ef41Sopenharmony_ci  xmlhttp.open("GET",
25761cb0ef41Sopenharmony_ci      "setpageaddress?%(query_dump)s&kind=" + kind +
25771cb0ef41Sopenharmony_ci      "&address=" + address);
25781cb0ef41Sopenharmony_ci  xmlhttp.send();
25791cb0ef41Sopenharmony_ci}
25801cb0ef41Sopenharmony_ci
25811cb0ef41Sopenharmony_ci</script>
25821cb0ef41Sopenharmony_ci
25831cb0ef41Sopenharmony_ci<title>Dump %(dump_name)s</title>
25841cb0ef41Sopenharmony_ci</head>
25851cb0ef41Sopenharmony_ci
25861cb0ef41Sopenharmony_ci<body>
25871cb0ef41Sopenharmony_ci  <div class="header">
25881cb0ef41Sopenharmony_ci    <form class="navigation" action="search.html">
25891cb0ef41Sopenharmony_ci      <a href="summary.html?%(query_dump)s">Context info</a>&nbsp;&nbsp;&nbsp;
25901cb0ef41Sopenharmony_ci      <a href="info.html?%(query_dump)s">Dump info</a>&nbsp;&nbsp;&nbsp;
25911cb0ef41Sopenharmony_ci      <a href="modules.html?%(query_dump)s">Modules</a>&nbsp;&nbsp;&nbsp;
25921cb0ef41Sopenharmony_ci      &nbsp;
25931cb0ef41Sopenharmony_ci      <input type="search" name="val">
25941cb0ef41Sopenharmony_ci      <input type="submit" name="search" value="Search">
25951cb0ef41Sopenharmony_ci      <input type="hidden" name="dump" value="%(dump_name)s">
25961cb0ef41Sopenharmony_ci    </form>
25971cb0ef41Sopenharmony_ci    <form class="navigation" action="disasm.html#highlight">
25981cb0ef41Sopenharmony_ci      &nbsp;
25991cb0ef41Sopenharmony_ci      &nbsp;
26001cb0ef41Sopenharmony_ci      &nbsp;
26011cb0ef41Sopenharmony_ci      <input type="search" name="val">
26021cb0ef41Sopenharmony_ci      <input type="submit" name="disasm" value="Disasm">
26031cb0ef41Sopenharmony_ci      &nbsp;
26041cb0ef41Sopenharmony_ci      &nbsp;
26051cb0ef41Sopenharmony_ci      &nbsp;
26061cb0ef41Sopenharmony_ci      <a href="dumps.html">Dumps...</a>
26071cb0ef41Sopenharmony_ci    </form>
26081cb0ef41Sopenharmony_ci  </div>
26091cb0ef41Sopenharmony_ci  <br>
26101cb0ef41Sopenharmony_ci  <hr>
26111cb0ef41Sopenharmony_ci"""
26121cb0ef41Sopenharmony_ci
26131cb0ef41Sopenharmony_ci
26141cb0ef41Sopenharmony_ciWEB_FOOTER = """
26151cb0ef41Sopenharmony_ci</body>
26161cb0ef41Sopenharmony_ci</html>
26171cb0ef41Sopenharmony_ci"""
26181cb0ef41Sopenharmony_ci
26191cb0ef41Sopenharmony_ci
26201cb0ef41Sopenharmony_ciclass WebParameterError(Exception):
26211cb0ef41Sopenharmony_ci  pass
26221cb0ef41Sopenharmony_ci
26231cb0ef41Sopenharmony_ci
26241cb0ef41Sopenharmony_ciclass InspectionWebHandler(http_server.BaseHTTPRequestHandler):
26251cb0ef41Sopenharmony_ci
26261cb0ef41Sopenharmony_ci  def formatter(self, query_components):
26271cb0ef41Sopenharmony_ci    name = query_components.get("dump", [None])[0]
26281cb0ef41Sopenharmony_ci    return self.server.get_dump_formatter(name)
26291cb0ef41Sopenharmony_ci
26301cb0ef41Sopenharmony_ci  def send_success_html_headers(self):
26311cb0ef41Sopenharmony_ci    self.send_response(200)
26321cb0ef41Sopenharmony_ci    self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
26331cb0ef41Sopenharmony_ci    self.send_header("Pragma", "no-cache")
26341cb0ef41Sopenharmony_ci    self.send_header("Expires", "0")
26351cb0ef41Sopenharmony_ci    self.send_header('Content-type','text/html')
26361cb0ef41Sopenharmony_ci    self.end_headers()
26371cb0ef41Sopenharmony_ci    return
26381cb0ef41Sopenharmony_ci
26391cb0ef41Sopenharmony_ci  def write(self, string):
26401cb0ef41Sopenharmony_ci    self.wfile.write(string.encode('utf-8'))
26411cb0ef41Sopenharmony_ci
26421cb0ef41Sopenharmony_ci  def do_GET(self):
26431cb0ef41Sopenharmony_ci    try:
26441cb0ef41Sopenharmony_ci      parsedurl = urllib.parse.urlparse(self.path)
26451cb0ef41Sopenharmony_ci      query_components = urllib.parse.parse_qs(parsedurl.query)
26461cb0ef41Sopenharmony_ci      out_buffer = io.StringIO()
26471cb0ef41Sopenharmony_ci      if parsedurl.path == "/dumps.html":
26481cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26491cb0ef41Sopenharmony_ci        self.server.output_dumps(out_buffer)
26501cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26511cb0ef41Sopenharmony_ci      elif parsedurl.path == "/summary.html":
26521cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26531cb0ef41Sopenharmony_ci        self.formatter(query_components).output_summary(out_buffer)
26541cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26551cb0ef41Sopenharmony_ci      elif parsedurl.path == "/info.html":
26561cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26571cb0ef41Sopenharmony_ci        self.formatter(query_components).output_info(out_buffer)
26581cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26591cb0ef41Sopenharmony_ci      elif parsedurl.path == "/modules.html":
26601cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26611cb0ef41Sopenharmony_ci        self.formatter(query_components).output_modules(out_buffer)
26621cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26631cb0ef41Sopenharmony_ci      elif parsedurl.path == "/search.html" or parsedurl.path == "/s":
26641cb0ef41Sopenharmony_ci        address = query_components.get("val", [])
26651cb0ef41Sopenharmony_ci        if len(address) != 1:
26661cb0ef41Sopenharmony_ci          self.send_error(404, "Invalid params")
26671cb0ef41Sopenharmony_ci          return
26681cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26691cb0ef41Sopenharmony_ci        self.formatter(query_components).output_search_res(
26701cb0ef41Sopenharmony_ci            out_buffer, address[0])
26711cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26721cb0ef41Sopenharmony_ci      elif parsedurl.path == "/disasm.html":
26731cb0ef41Sopenharmony_ci        address = query_components.get("val", [])
26741cb0ef41Sopenharmony_ci        exact = query_components.get("exact", ["on"])
26751cb0ef41Sopenharmony_ci        if len(address) != 1:
26761cb0ef41Sopenharmony_ci          self.send_error(404, "Invalid params")
26771cb0ef41Sopenharmony_ci          return
26781cb0ef41Sopenharmony_ci        self.send_success_html_headers()
26791cb0ef41Sopenharmony_ci        self.formatter(query_components).output_disasm(
26801cb0ef41Sopenharmony_ci            out_buffer, address[0], exact[0])
26811cb0ef41Sopenharmony_ci        self.write(out_buffer.getvalue())
26821cb0ef41Sopenharmony_ci      elif parsedurl.path == "/data.html":
26831cb0ef41Sopenharmony_ci        address = query_components.get("val", [])
26841cb0ef41Sopenharmony_ci        datakind = query_components.get("type", ["address"])
26851cb0ef41Sopenharmony_ci        if len(address) == 1 and len(datakind) == 1:
26861cb0ef41Sopenharmony_ci          self.send_success_html_headers()
26871cb0ef41Sopenharmony_ci          self.formatter(query_components).output_data(
26881cb0ef41Sopenharmony_ci              out_buffer, address[0], datakind[0])
26891cb0ef41Sopenharmony_ci          self.write(out_buffer.getvalue())
26901cb0ef41Sopenharmony_ci        else:
26911cb0ef41Sopenharmony_ci          self.send_error(404,'Invalid params')
26921cb0ef41Sopenharmony_ci      elif parsedurl.path == "/setdumpdesc":
26931cb0ef41Sopenharmony_ci        name = query_components.get("dump", [""])
26941cb0ef41Sopenharmony_ci        description = query_components.get("description", [""])
26951cb0ef41Sopenharmony_ci        if len(name) == 1 and len(description) == 1:
26961cb0ef41Sopenharmony_ci          name = name[0]
26971cb0ef41Sopenharmony_ci          description = description[0]
26981cb0ef41Sopenharmony_ci          if self.server.set_dump_desc(name, description):
26991cb0ef41Sopenharmony_ci            self.send_success_html_headers()
27001cb0ef41Sopenharmony_ci            self.write("OK")
27011cb0ef41Sopenharmony_ci            return
27021cb0ef41Sopenharmony_ci        self.send_error(404,'Invalid params')
27031cb0ef41Sopenharmony_ci      elif parsedurl.path == "/setcomment":
27041cb0ef41Sopenharmony_ci        address = query_components.get("address", [])
27051cb0ef41Sopenharmony_ci        comment = query_components.get("comment", [""])
27061cb0ef41Sopenharmony_ci        if len(address) == 1 and len(comment) == 1:
27071cb0ef41Sopenharmony_ci          address = address[0]
27081cb0ef41Sopenharmony_ci          comment = comment[0]
27091cb0ef41Sopenharmony_ci          self.formatter(query_components).set_comment(address, comment)
27101cb0ef41Sopenharmony_ci          self.send_success_html_headers()
27111cb0ef41Sopenharmony_ci          self.write("OK")
27121cb0ef41Sopenharmony_ci        else:
27131cb0ef41Sopenharmony_ci          self.send_error(404,'Invalid params')
27141cb0ef41Sopenharmony_ci      elif parsedurl.path == "/setpageaddress":
27151cb0ef41Sopenharmony_ci        kind = query_components.get("kind", [])
27161cb0ef41Sopenharmony_ci        address = query_components.get("address", [""])
27171cb0ef41Sopenharmony_ci        if len(kind) == 1 and len(address) == 1:
27181cb0ef41Sopenharmony_ci          kind = kind[0]
27191cb0ef41Sopenharmony_ci          address = address[0]
27201cb0ef41Sopenharmony_ci          self.formatter(query_components).set_page_address(kind, address)
27211cb0ef41Sopenharmony_ci          self.send_success_html_headers()
27221cb0ef41Sopenharmony_ci          self.write("OK")
27231cb0ef41Sopenharmony_ci        else:
27241cb0ef41Sopenharmony_ci          self.send_error(404,'Invalid params')
27251cb0ef41Sopenharmony_ci      else:
27261cb0ef41Sopenharmony_ci        self.send_error(404,'File Not Found: %s' % self.path)
27271cb0ef41Sopenharmony_ci
27281cb0ef41Sopenharmony_ci    except IOError:
27291cb0ef41Sopenharmony_ci      self.send_error(404,'File Not Found: %s' % self.path)
27301cb0ef41Sopenharmony_ci
27311cb0ef41Sopenharmony_ci    except WebParameterError as e:
27321cb0ef41Sopenharmony_ci      self.send_error(404, 'Web parameter error: %s' % e.message)
27331cb0ef41Sopenharmony_ci
27341cb0ef41Sopenharmony_ci
27351cb0ef41Sopenharmony_ciHTML_REG_FORMAT = "<span class=\"register\"><b>%s</b>:&nbsp;%s</span><br/>\n"
27361cb0ef41Sopenharmony_ci
27371cb0ef41Sopenharmony_ci
27381cb0ef41Sopenharmony_ciclass InspectionWebFormatter(object):
27391cb0ef41Sopenharmony_ci  CONTEXT_FULL = 0
27401cb0ef41Sopenharmony_ci  CONTEXT_SHORT = 1
27411cb0ef41Sopenharmony_ci
27421cb0ef41Sopenharmony_ci  def __init__(self, switches, minidump_name, http_server):
27431cb0ef41Sopenharmony_ci    self.dumpfilename = os.path.split(minidump_name)[1]
27441cb0ef41Sopenharmony_ci    self.encfilename = urllib.parse.urlencode({'dump': self.dumpfilename})
27451cb0ef41Sopenharmony_ci    self.reader = MinidumpReader(switches, minidump_name)
27461cb0ef41Sopenharmony_ci    self.server = http_server
27471cb0ef41Sopenharmony_ci
27481cb0ef41Sopenharmony_ci    # Set up the heap
27491cb0ef41Sopenharmony_ci    exception_thread = self.reader.thread_map[self.reader.exception.thread_id]
27501cb0ef41Sopenharmony_ci    stack_top = self.reader.ExceptionSP()
27511cb0ef41Sopenharmony_ci    stack_bottom = exception_thread.stack.start + \
27521cb0ef41Sopenharmony_ci        exception_thread.stack.memory.data_size
27531cb0ef41Sopenharmony_ci    stack_map = {self.reader.ExceptionIP(): -1}
27541cb0ef41Sopenharmony_ci    for slot in range(stack_top, stack_bottom,
27551cb0ef41Sopenharmony_ci                      self.reader.MachinePointerSize()):
27561cb0ef41Sopenharmony_ci      maybe_address = self.reader.ReadUIntPtr(slot)
27571cb0ef41Sopenharmony_ci      if not maybe_address in stack_map:
27581cb0ef41Sopenharmony_ci        stack_map[maybe_address] = slot
27591cb0ef41Sopenharmony_ci    self.heap = V8Heap(self.reader, stack_map)
27601cb0ef41Sopenharmony_ci
27611cb0ef41Sopenharmony_ci    self.padawan = InspectionPadawan(self.reader, self.heap)
27621cb0ef41Sopenharmony_ci    self.comments = InspectionInfo(minidump_name, self.reader)
27631cb0ef41Sopenharmony_ci    self.padawan.known_first_old_page = (
27641cb0ef41Sopenharmony_ci        self.comments.get_page_address("oldpage"))
27651cb0ef41Sopenharmony_ci    self.padawan.known_first_map_page = (
27661cb0ef41Sopenharmony_ci        self.comments.get_page_address("mappage"))
27671cb0ef41Sopenharmony_ci
27681cb0ef41Sopenharmony_ci  def set_comment(self, straddress, comment):
27691cb0ef41Sopenharmony_ci    try:
27701cb0ef41Sopenharmony_ci      address = int(straddress, 0)
27711cb0ef41Sopenharmony_ci      self.comments.set_comment(address, comment)
27721cb0ef41Sopenharmony_ci    except ValueError:
27731cb0ef41Sopenharmony_ci      print("Invalid address")
27741cb0ef41Sopenharmony_ci
27751cb0ef41Sopenharmony_ci  def set_page_address(self, kind, straddress):
27761cb0ef41Sopenharmony_ci    try:
27771cb0ef41Sopenharmony_ci      address = int(straddress, 0)
27781cb0ef41Sopenharmony_ci      if kind == "oldpage":
27791cb0ef41Sopenharmony_ci        self.padawan.known_first_old_page = address
27801cb0ef41Sopenharmony_ci      elif kind == "mappage":
27811cb0ef41Sopenharmony_ci        self.padawan.known_first_map_page = address
27821cb0ef41Sopenharmony_ci      self.comments.save_page_address(kind, address)
27831cb0ef41Sopenharmony_ci    except ValueError:
27841cb0ef41Sopenharmony_ci      print("Invalid address")
27851cb0ef41Sopenharmony_ci
27861cb0ef41Sopenharmony_ci  def td_from_address(self, f, address):
27871cb0ef41Sopenharmony_ci    f.write("<td %s>" % self.comments.get_style_class_string(address))
27881cb0ef41Sopenharmony_ci
27891cb0ef41Sopenharmony_ci  def format_address(self, maybeaddress, straddress = None):
27901cb0ef41Sopenharmony_ci    if maybeaddress is None:
27911cb0ef41Sopenharmony_ci      return "not in dump"
27921cb0ef41Sopenharmony_ci    else:
27931cb0ef41Sopenharmony_ci      if straddress is None:
27941cb0ef41Sopenharmony_ci        straddress = "0x" + self.reader.FormatIntPtr(maybeaddress)
27951cb0ef41Sopenharmony_ci      style_class = ""
27961cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(maybeaddress):
27971cb0ef41Sopenharmony_ci        style_class = "class=nd"
27981cb0ef41Sopenharmony_ci      return ("<a %s href=s?%s&amp;val=%s>%s</a>" %
27991cb0ef41Sopenharmony_ci              (style_class, self.encfilename, straddress, straddress))
28001cb0ef41Sopenharmony_ci
28011cb0ef41Sopenharmony_ci  def format_onheap_address(self, size, maybeaddress, uncompressed):
28021cb0ef41Sopenharmony_ci    if maybeaddress is None:
28031cb0ef41Sopenharmony_ci      return "not in dump"
28041cb0ef41Sopenharmony_ci    else:
28051cb0ef41Sopenharmony_ci      straddress = "0x" + self.reader.FormatTagged(maybeaddress)
28061cb0ef41Sopenharmony_ci      struncompressed = "0x" + self.reader.FormatIntPtr(uncompressed)
28071cb0ef41Sopenharmony_ci      style_class = ""
28081cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(maybeaddress):
28091cb0ef41Sopenharmony_ci        style_class = "class=nd"
28101cb0ef41Sopenharmony_ci      return ("<a %s href=s?%s&amp;val=%s>%s</a>" %
28111cb0ef41Sopenharmony_ci              (style_class, self.encfilename, struncompressed, straddress))
28121cb0ef41Sopenharmony_ci
28131cb0ef41Sopenharmony_ci  def output_header(self, f):
28141cb0ef41Sopenharmony_ci    f.write(WEB_HEADER % {
28151cb0ef41Sopenharmony_ci        "query_dump": self.encfilename,
28161cb0ef41Sopenharmony_ci        "dump_name": html.escape(self.dumpfilename)
28171cb0ef41Sopenharmony_ci    })
28181cb0ef41Sopenharmony_ci
28191cb0ef41Sopenharmony_ci  def output_footer(self, f):
28201cb0ef41Sopenharmony_ci    f.write(WEB_FOOTER)
28211cb0ef41Sopenharmony_ci
28221cb0ef41Sopenharmony_ci  MAX_CONTEXT_STACK = 2048
28231cb0ef41Sopenharmony_ci
28241cb0ef41Sopenharmony_ci  def output_summary(self, f):
28251cb0ef41Sopenharmony_ci    self.output_header(f)
28261cb0ef41Sopenharmony_ci    f.write('<div class="code">')
28271cb0ef41Sopenharmony_ci    self.output_context(f, InspectionWebFormatter.CONTEXT_SHORT)
28281cb0ef41Sopenharmony_ci    self.output_disasm_pc(f)
28291cb0ef41Sopenharmony_ci
28301cb0ef41Sopenharmony_ci    # Output stack
28311cb0ef41Sopenharmony_ci    exception_thread = self.reader.thread_map[self.reader.exception.thread_id]
28321cb0ef41Sopenharmony_ci    stack_top = self.reader.ExceptionSP()
28331cb0ef41Sopenharmony_ci    stack_bottom = min(exception_thread.stack.start + \
28341cb0ef41Sopenharmony_ci        exception_thread.stack.memory.data_size,
28351cb0ef41Sopenharmony_ci        stack_top + self.MAX_CONTEXT_STACK)
28361cb0ef41Sopenharmony_ci    self.output_words(f, stack_top - 16, stack_bottom, stack_top, "Stack",
28371cb0ef41Sopenharmony_ci                      self.heap.MachinePointerSize())
28381cb0ef41Sopenharmony_ci
28391cb0ef41Sopenharmony_ci    f.write('</div>')
28401cb0ef41Sopenharmony_ci    self.output_footer(f)
28411cb0ef41Sopenharmony_ci    return
28421cb0ef41Sopenharmony_ci
28431cb0ef41Sopenharmony_ci  def output_info(self, f):
28441cb0ef41Sopenharmony_ci    self.output_header(f)
28451cb0ef41Sopenharmony_ci    f.write("<h3>Dump info</h3>")
28461cb0ef41Sopenharmony_ci    f.write("Description: ")
28471cb0ef41Sopenharmony_ci    self.server.output_dump_desc_field(f, self.dumpfilename)
28481cb0ef41Sopenharmony_ci    f.write("<br>")
28491cb0ef41Sopenharmony_ci    f.write("Filename: ")
28501cb0ef41Sopenharmony_ci    f.write("<span class=\"code\">%s</span><br>" % (self.dumpfilename))
28511cb0ef41Sopenharmony_ci    dt = datetime.datetime.fromtimestamp(self.reader.header.time_date_stampt)
28521cb0ef41Sopenharmony_ci    f.write("Timestamp: %s<br>" % dt.strftime('%Y-%m-%d %H:%M:%S'))
28531cb0ef41Sopenharmony_ci    self.output_context(f, InspectionWebFormatter.CONTEXT_FULL)
28541cb0ef41Sopenharmony_ci    self.output_address_ranges(f)
28551cb0ef41Sopenharmony_ci    self.output_footer(f)
28561cb0ef41Sopenharmony_ci    return
28571cb0ef41Sopenharmony_ci
28581cb0ef41Sopenharmony_ci  def output_address_ranges(self, f):
28591cb0ef41Sopenharmony_ci    regions = {}
28601cb0ef41Sopenharmony_ci    def print_region(_reader, start, size, _location):
28611cb0ef41Sopenharmony_ci      regions[start] = size
28621cb0ef41Sopenharmony_ci    self.reader.ForEachMemoryRegion(print_region)
28631cb0ef41Sopenharmony_ci    f.write("<h3>Available memory regions</h3>")
28641cb0ef41Sopenharmony_ci    f.write('<div class="code">')
28651cb0ef41Sopenharmony_ci    f.write("<table class=\"regions\">")
28661cb0ef41Sopenharmony_ci    f.write("<thead><tr>")
28671cb0ef41Sopenharmony_ci    f.write("<th>Start address</th>")
28681cb0ef41Sopenharmony_ci    f.write("<th>End address</th>")
28691cb0ef41Sopenharmony_ci    f.write("<th>Number of bytes</th>")
28701cb0ef41Sopenharmony_ci    f.write("</tr></thead>")
28711cb0ef41Sopenharmony_ci    for start in sorted(regions):
28721cb0ef41Sopenharmony_ci      size = regions[start]
28731cb0ef41Sopenharmony_ci      f.write("<tr>")
28741cb0ef41Sopenharmony_ci      f.write("<td>%s</td>" % self.format_address(start))
28751cb0ef41Sopenharmony_ci      f.write("<td>&nbsp;%s</td>" % self.format_address(start + size))
28761cb0ef41Sopenharmony_ci      f.write("<td>&nbsp;%d</td>" % size)
28771cb0ef41Sopenharmony_ci      f.write("</tr>")
28781cb0ef41Sopenharmony_ci    f.write("</table>")
28791cb0ef41Sopenharmony_ci    f.write('</div>')
28801cb0ef41Sopenharmony_ci    return
28811cb0ef41Sopenharmony_ci
28821cb0ef41Sopenharmony_ci  def output_module_details(self, f, module):
28831cb0ef41Sopenharmony_ci    f.write("<b>%s</b>" % GetModuleName(self.reader, module))
28841cb0ef41Sopenharmony_ci    file_version = GetVersionString(module.version_info.dwFileVersionMS,
28851cb0ef41Sopenharmony_ci                                    module.version_info.dwFileVersionLS)
28861cb0ef41Sopenharmony_ci    product_version = GetVersionString(module.version_info.dwProductVersionMS,
28871cb0ef41Sopenharmony_ci                                       module.version_info.dwProductVersionLS)
28881cb0ef41Sopenharmony_ci    f.write("<br>&nbsp;&nbsp;")
28891cb0ef41Sopenharmony_ci    f.write("base: %s" % self.reader.FormatIntPtr(module.base_of_image))
28901cb0ef41Sopenharmony_ci    f.write("<br>&nbsp;&nbsp;")
28911cb0ef41Sopenharmony_ci    f.write("  end: %s" % self.reader.FormatIntPtr(module.base_of_image +
28921cb0ef41Sopenharmony_ci                                            module.size_of_image))
28931cb0ef41Sopenharmony_ci    f.write("<br>&nbsp;&nbsp;")
28941cb0ef41Sopenharmony_ci    f.write("  file version: %s" % file_version)
28951cb0ef41Sopenharmony_ci    f.write("<br>&nbsp;&nbsp;")
28961cb0ef41Sopenharmony_ci    f.write("  product version: %s" % product_version)
28971cb0ef41Sopenharmony_ci    f.write("<br>&nbsp;&nbsp;")
28981cb0ef41Sopenharmony_ci    time_date_stamp = datetime.datetime.fromtimestamp(module.time_date_stamp)
28991cb0ef41Sopenharmony_ci    f.write("  timestamp: %s" % time_date_stamp)
29001cb0ef41Sopenharmony_ci    f.write("<br>");
29011cb0ef41Sopenharmony_ci
29021cb0ef41Sopenharmony_ci  def output_modules(self, f):
29031cb0ef41Sopenharmony_ci    self.output_header(f)
29041cb0ef41Sopenharmony_ci    f.write('<div class="code">')
29051cb0ef41Sopenharmony_ci    for module in self.reader.module_list.modules:
29061cb0ef41Sopenharmony_ci      self.output_module_details(f, module)
29071cb0ef41Sopenharmony_ci    f.write("</div>")
29081cb0ef41Sopenharmony_ci    self.output_footer(f)
29091cb0ef41Sopenharmony_ci    return
29101cb0ef41Sopenharmony_ci
29111cb0ef41Sopenharmony_ci  def output_context(self, f, details):
29121cb0ef41Sopenharmony_ci    exception_thread = self.reader.thread_map[self.reader.exception.thread_id]
29131cb0ef41Sopenharmony_ci    f.write("<h3>Exception context</h3>")
29141cb0ef41Sopenharmony_ci    f.write('<div class="code">')
29151cb0ef41Sopenharmony_ci    f.write("Thread id: %d" % exception_thread.id)
29161cb0ef41Sopenharmony_ci    f.write("&nbsp;&nbsp; Exception code: %08X<br/>" %
29171cb0ef41Sopenharmony_ci            self.reader.exception.exception.code)
29181cb0ef41Sopenharmony_ci    if details == InspectionWebFormatter.CONTEXT_FULL:
29191cb0ef41Sopenharmony_ci      if self.reader.exception.exception.parameter_count > 0:
29201cb0ef41Sopenharmony_ci        f.write("&nbsp;&nbsp; Exception parameters: ")
29211cb0ef41Sopenharmony_ci        for i in range(0, self.reader.exception.exception.parameter_count):
29221cb0ef41Sopenharmony_ci          f.write("%08x" % self.reader.exception.exception.information[i])
29231cb0ef41Sopenharmony_ci        f.write("<br><br>")
29241cb0ef41Sopenharmony_ci
29251cb0ef41Sopenharmony_ci    for r in CONTEXT_FOR_ARCH[self.reader.arch]:
29261cb0ef41Sopenharmony_ci      f.write(HTML_REG_FORMAT %
29271cb0ef41Sopenharmony_ci              (r, self.format_address(self.reader.Register(r))))
29281cb0ef41Sopenharmony_ci    # TODO(vitalyr): decode eflags.
29291cb0ef41Sopenharmony_ci    if self.reader.arch in [MD_CPU_ARCHITECTURE_ARM, MD_CPU_ARCHITECTURE_ARM64]:
29301cb0ef41Sopenharmony_ci      f.write("<b>cpsr</b>: %s" % bin(self.reader.exception_context.cpsr)[2:])
29311cb0ef41Sopenharmony_ci    else:
29321cb0ef41Sopenharmony_ci      f.write("<b>eflags</b>: %s" %
29331cb0ef41Sopenharmony_ci              bin(self.reader.exception_context.eflags)[2:])
29341cb0ef41Sopenharmony_ci    f.write('</div>')
29351cb0ef41Sopenharmony_ci    return
29361cb0ef41Sopenharmony_ci
29371cb0ef41Sopenharmony_ci  def align_down(self, a, size):
29381cb0ef41Sopenharmony_ci    alignment_correction = a % size
29391cb0ef41Sopenharmony_ci    return a - alignment_correction
29401cb0ef41Sopenharmony_ci
29411cb0ef41Sopenharmony_ci  def align_up(self, a, size):
29421cb0ef41Sopenharmony_ci    alignment_correction = (size - 1) - ((a + size - 1) % size)
29431cb0ef41Sopenharmony_ci    return a + alignment_correction
29441cb0ef41Sopenharmony_ci
29451cb0ef41Sopenharmony_ci  def format_object(self, address):
29461cb0ef41Sopenharmony_ci    heap_object = self.padawan.SenseObject(address)
29471cb0ef41Sopenharmony_ci    return html.escape(str(heap_object or ""))
29481cb0ef41Sopenharmony_ci
29491cb0ef41Sopenharmony_ci  def output_data(self, f, straddress, datakind):
29501cb0ef41Sopenharmony_ci    try:
29511cb0ef41Sopenharmony_ci      self.output_header(f)
29521cb0ef41Sopenharmony_ci      address = int(straddress, 0)
29531cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(address):
29541cb0ef41Sopenharmony_ci        f.write("<h3>Address 0x%x not found in the dump.</h3>" % address)
29551cb0ef41Sopenharmony_ci        return
29561cb0ef41Sopenharmony_ci      region = self.reader.FindRegion(address)
29571cb0ef41Sopenharmony_ci      if datakind == "address":
29581cb0ef41Sopenharmony_ci        self.output_words(f, region[0], region[0] + region[1], address, "Dump",
29591cb0ef41Sopenharmony_ci                          self.heap.MachinePointerSize())
29601cb0ef41Sopenharmony_ci      if datakind == "tagged":
29611cb0ef41Sopenharmony_ci        self.output_words(f, region[0], region[0] + region[1], address,
29621cb0ef41Sopenharmony_ci                          "Tagged Dump", self.heap.TaggedPointerSize())
29631cb0ef41Sopenharmony_ci      elif datakind == "ascii":
29641cb0ef41Sopenharmony_ci        self.output_ascii(f, region[0], region[0] + region[1], address)
29651cb0ef41Sopenharmony_ci      self.output_footer(f)
29661cb0ef41Sopenharmony_ci
29671cb0ef41Sopenharmony_ci    except ValueError:
29681cb0ef41Sopenharmony_ci      f.write("<h3>Unrecognized address format \"%s\".</h3>" % straddress)
29691cb0ef41Sopenharmony_ci    return
29701cb0ef41Sopenharmony_ci
29711cb0ef41Sopenharmony_ci  def output_words(self, f, start_address, end_address, highlight_address, desc,
29721cb0ef41Sopenharmony_ci                   size):
29731cb0ef41Sopenharmony_ci    region = self.reader.FindRegion(highlight_address)
29741cb0ef41Sopenharmony_ci    if region is None:
29751cb0ef41Sopenharmony_ci      f.write("<h3>Address 0x%x not found in the dump.</h3>" %
29761cb0ef41Sopenharmony_ci              (highlight_address))
29771cb0ef41Sopenharmony_ci      return
29781cb0ef41Sopenharmony_ci    start_address = self.align_down(start_address, size)
29791cb0ef41Sopenharmony_ci    low = self.align_down(region[0], size)
29801cb0ef41Sopenharmony_ci    high = self.align_up(region[0] + region[1], size)
29811cb0ef41Sopenharmony_ci    if start_address < low:
29821cb0ef41Sopenharmony_ci      start_address = low
29831cb0ef41Sopenharmony_ci    end_address = self.align_up(end_address, size)
29841cb0ef41Sopenharmony_ci    if end_address > high:
29851cb0ef41Sopenharmony_ci      end_address = high
29861cb0ef41Sopenharmony_ci
29871cb0ef41Sopenharmony_ci    expand = ""
29881cb0ef41Sopenharmony_ci    if start_address != low or end_address != high:
29891cb0ef41Sopenharmony_ci      expand = ("(<a href=\"data.html?%s&amp;val=0x%x#highlight\">"
29901cb0ef41Sopenharmony_ci                " more..."
29911cb0ef41Sopenharmony_ci                " </a>)" %
29921cb0ef41Sopenharmony_ci                (self.encfilename, highlight_address))
29931cb0ef41Sopenharmony_ci
29941cb0ef41Sopenharmony_ci    f.write("<h3>%s 0x%x - 0x%x, "
29951cb0ef41Sopenharmony_ci            "highlighting <a href=\"#highlight\">0x%x</a> %s</h3>" %
29961cb0ef41Sopenharmony_ci            (desc, start_address, end_address, highlight_address, expand))
29971cb0ef41Sopenharmony_ci    f.write('<div class="code">')
29981cb0ef41Sopenharmony_ci    f.write("<table class=codedump>")
29991cb0ef41Sopenharmony_ci
30001cb0ef41Sopenharmony_ci    for j in range(0, end_address - start_address, size):
30011cb0ef41Sopenharmony_ci      slot = start_address + j
30021cb0ef41Sopenharmony_ci      heap_object = ""
30031cb0ef41Sopenharmony_ci      maybe_address = None
30041cb0ef41Sopenharmony_ci      maybe_uncompressed_address = None
30051cb0ef41Sopenharmony_ci      end_region = region[0] + region[1]
30061cb0ef41Sopenharmony_ci      if slot < region[0] or slot + size > end_region:
30071cb0ef41Sopenharmony_ci        straddress = "0x"
30081cb0ef41Sopenharmony_ci        for i in range(end_region, slot + size):
30091cb0ef41Sopenharmony_ci          straddress += "??"
30101cb0ef41Sopenharmony_ci        for i in reversed(
30111cb0ef41Sopenharmony_ci            range(max(slot, region[0]), min(slot + size, end_region))):
30121cb0ef41Sopenharmony_ci          straddress += "%02x" % self.reader.ReadU8(i)
30131cb0ef41Sopenharmony_ci        for i in range(slot, region[0]):
30141cb0ef41Sopenharmony_ci          straddress += "??"
30151cb0ef41Sopenharmony_ci      else:
30161cb0ef41Sopenharmony_ci        maybe_address = self.reader.ReadSized(slot, size)
30171cb0ef41Sopenharmony_ci        if size == self.reader.MachinePointerSize():
30181cb0ef41Sopenharmony_ci          maybe_uncompressed_address = maybe_address
30191cb0ef41Sopenharmony_ci        else:
30201cb0ef41Sopenharmony_ci          maybe_uncompressed_address = (slot & (0xFFFFFF << 32)) | (
30211cb0ef41Sopenharmony_ci              maybe_address & 0xFFFFFF)
30221cb0ef41Sopenharmony_ci
30231cb0ef41Sopenharmony_ci        if size == self.reader.TaggedPointerSize():
30241cb0ef41Sopenharmony_ci          straddress = self.format_onheap_address(size, maybe_address,
30251cb0ef41Sopenharmony_ci                                                  maybe_uncompressed_address)
30261cb0ef41Sopenharmony_ci          if maybe_address:
30271cb0ef41Sopenharmony_ci            heap_object = self.format_object(maybe_address)
30281cb0ef41Sopenharmony_ci        else:
30291cb0ef41Sopenharmony_ci          straddress = self.format_address(maybe_address)
30301cb0ef41Sopenharmony_ci
30311cb0ef41Sopenharmony_ci      address_fmt = "%s&nbsp;</td>"
30321cb0ef41Sopenharmony_ci      if slot == highlight_address:
30331cb0ef41Sopenharmony_ci        f.write("<tr class=highlight-line>")
30341cb0ef41Sopenharmony_ci        address_fmt = "<a id=highlight></a>%s&nbsp;</td>"
30351cb0ef41Sopenharmony_ci      elif slot < highlight_address and highlight_address < slot + size:
30361cb0ef41Sopenharmony_ci        f.write("<tr class=inexact-highlight-line>")
30371cb0ef41Sopenharmony_ci        address_fmt = "<a id=highlight></a>%s&nbsp;</td>"
30381cb0ef41Sopenharmony_ci      else:
30391cb0ef41Sopenharmony_ci        f.write("<tr>")
30401cb0ef41Sopenharmony_ci
30411cb0ef41Sopenharmony_ci      f.write("<td>")
30421cb0ef41Sopenharmony_ci      self.output_comment_box(f, "da-", slot)
30431cb0ef41Sopenharmony_ci      f.write("</td>")
30441cb0ef41Sopenharmony_ci      self.td_from_address(f, slot)
30451cb0ef41Sopenharmony_ci      f.write(address_fmt % self.format_address(slot))
30461cb0ef41Sopenharmony_ci      self.td_from_address(f, maybe_uncompressed_address)
30471cb0ef41Sopenharmony_ci      f.write(":&nbsp;%s&nbsp;</td>" % straddress)
30481cb0ef41Sopenharmony_ci      f.write("<td>")
30491cb0ef41Sopenharmony_ci      if maybe_uncompressed_address != None:
30501cb0ef41Sopenharmony_ci        self.output_comment_box(f, "sv-" + self.reader.FormatIntPtr(slot),
30511cb0ef41Sopenharmony_ci                                maybe_uncompressed_address)
30521cb0ef41Sopenharmony_ci      f.write("</td>")
30531cb0ef41Sopenharmony_ci      f.write("<td>%s</td>" % (heap_object or ''))
30541cb0ef41Sopenharmony_ci      f.write("</tr>")
30551cb0ef41Sopenharmony_ci    f.write("</table>")
30561cb0ef41Sopenharmony_ci    f.write("</div>")
30571cb0ef41Sopenharmony_ci    return
30581cb0ef41Sopenharmony_ci
30591cb0ef41Sopenharmony_ci  def output_ascii(self, f, start_address, end_address, highlight_address):
30601cb0ef41Sopenharmony_ci    region = self.reader.FindRegion(highlight_address)
30611cb0ef41Sopenharmony_ci    if region is None:
30621cb0ef41Sopenharmony_ci      f.write("<h3>Address %x not found in the dump.</h3>" %
30631cb0ef41Sopenharmony_ci          highlight_address)
30641cb0ef41Sopenharmony_ci      return
30651cb0ef41Sopenharmony_ci    if start_address < region[0]:
30661cb0ef41Sopenharmony_ci      start_address = region[0]
30671cb0ef41Sopenharmony_ci    if end_address > region[0] + region[1]:
30681cb0ef41Sopenharmony_ci      end_address = region[0] + region[1]
30691cb0ef41Sopenharmony_ci
30701cb0ef41Sopenharmony_ci    expand = ""
30711cb0ef41Sopenharmony_ci    if start_address != region[0] or end_address != region[0] + region[1]:
30721cb0ef41Sopenharmony_ci      link = ("data.html?%s&amp;val=0x%x&amp;type=ascii#highlight" %
30731cb0ef41Sopenharmony_ci              (self.encfilename, highlight_address))
30741cb0ef41Sopenharmony_ci      expand = "(<a href=\"%s\">more...</a>)" % link
30751cb0ef41Sopenharmony_ci
30761cb0ef41Sopenharmony_ci    f.write("<h3>ASCII dump 0x%x - 0x%x, highlighting 0x%x %s</h3>" %
30771cb0ef41Sopenharmony_ci            (start_address, end_address, highlight_address, expand))
30781cb0ef41Sopenharmony_ci
30791cb0ef41Sopenharmony_ci    line_width = 64
30801cb0ef41Sopenharmony_ci
30811cb0ef41Sopenharmony_ci    f.write('<div class="code">')
30821cb0ef41Sopenharmony_ci
30831cb0ef41Sopenharmony_ci    start = self.align_down(start_address, line_width)
30841cb0ef41Sopenharmony_ci
30851cb0ef41Sopenharmony_ci    for i in range(end_address - start):
30861cb0ef41Sopenharmony_ci      address = start + i
30871cb0ef41Sopenharmony_ci      if address % 64 == 0:
30881cb0ef41Sopenharmony_ci        if address != start:
30891cb0ef41Sopenharmony_ci          f.write("<br>")
30901cb0ef41Sopenharmony_ci        f.write("0x%08x:&nbsp;" % address)
30911cb0ef41Sopenharmony_ci      if address < start_address:
30921cb0ef41Sopenharmony_ci        f.write("&nbsp;")
30931cb0ef41Sopenharmony_ci      else:
30941cb0ef41Sopenharmony_ci        if address == highlight_address:
30951cb0ef41Sopenharmony_ci          f.write("<span class=\"highlight\">")
30961cb0ef41Sopenharmony_ci        code = self.reader.ReadU8(address)
30971cb0ef41Sopenharmony_ci        if code < 127 and code >= 32:
30981cb0ef41Sopenharmony_ci          f.write("&#")
30991cb0ef41Sopenharmony_ci          f.write(str(code))
31001cb0ef41Sopenharmony_ci          f.write(";")
31011cb0ef41Sopenharmony_ci        else:
31021cb0ef41Sopenharmony_ci          f.write("&middot;")
31031cb0ef41Sopenharmony_ci        if address == highlight_address:
31041cb0ef41Sopenharmony_ci          f.write("</span>")
31051cb0ef41Sopenharmony_ci    f.write("</div>")
31061cb0ef41Sopenharmony_ci    return
31071cb0ef41Sopenharmony_ci
31081cb0ef41Sopenharmony_ci  def output_disasm(self, f, straddress, strexact):
31091cb0ef41Sopenharmony_ci    try:
31101cb0ef41Sopenharmony_ci      self.output_header(f)
31111cb0ef41Sopenharmony_ci      address = int(straddress, 0)
31121cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(address):
31131cb0ef41Sopenharmony_ci        f.write("<h3>Address 0x%x not found in the dump.</h3>" % address)
31141cb0ef41Sopenharmony_ci        return
31151cb0ef41Sopenharmony_ci      region = self.reader.FindRegion(address)
31161cb0ef41Sopenharmony_ci      self.output_disasm_range(
31171cb0ef41Sopenharmony_ci          f, region[0], region[0] + region[1], address, strexact == "on")
31181cb0ef41Sopenharmony_ci      self.output_footer(f)
31191cb0ef41Sopenharmony_ci    except ValueError:
31201cb0ef41Sopenharmony_ci      f.write("<h3>Unrecognized address format \"%s\".</h3>" % straddress)
31211cb0ef41Sopenharmony_ci    return
31221cb0ef41Sopenharmony_ci
31231cb0ef41Sopenharmony_ci  def output_disasm_range(
31241cb0ef41Sopenharmony_ci      self, f, start_address, end_address, highlight_address, exact):
31251cb0ef41Sopenharmony_ci    region = self.reader.FindRegion(highlight_address)
31261cb0ef41Sopenharmony_ci    if start_address < region[0]:
31271cb0ef41Sopenharmony_ci      start_address = region[0]
31281cb0ef41Sopenharmony_ci    if end_address > region[0] + region[1]:
31291cb0ef41Sopenharmony_ci      end_address = region[0] + region[1]
31301cb0ef41Sopenharmony_ci    count = end_address - start_address
31311cb0ef41Sopenharmony_ci    lines = self.reader.GetDisasmLines(start_address, count)
31321cb0ef41Sopenharmony_ci    found = False
31331cb0ef41Sopenharmony_ci    if exact:
31341cb0ef41Sopenharmony_ci      for line in lines:
31351cb0ef41Sopenharmony_ci        if line[0] + start_address == highlight_address:
31361cb0ef41Sopenharmony_ci          found = True
31371cb0ef41Sopenharmony_ci          break
31381cb0ef41Sopenharmony_ci      if not found:
31391cb0ef41Sopenharmony_ci        start_address = highlight_address
31401cb0ef41Sopenharmony_ci        count = end_address - start_address
31411cb0ef41Sopenharmony_ci        lines = self.reader.GetDisasmLines(highlight_address, count)
31421cb0ef41Sopenharmony_ci    expand = ""
31431cb0ef41Sopenharmony_ci    if start_address != region[0] or end_address != region[0] + region[1]:
31441cb0ef41Sopenharmony_ci      exactness = ""
31451cb0ef41Sopenharmony_ci      if exact and not found and end_address == region[0] + region[1]:
31461cb0ef41Sopenharmony_ci        exactness = "&amp;exact=off"
31471cb0ef41Sopenharmony_ci      expand = ("(<a href=\"disasm.html?%s%s"
31481cb0ef41Sopenharmony_ci                "&amp;val=0x%x#highlight\">more...</a>)" %
31491cb0ef41Sopenharmony_ci                (self.encfilename, exactness, highlight_address))
31501cb0ef41Sopenharmony_ci
31511cb0ef41Sopenharmony_ci    f.write("<h3>Disassembling 0x%x - 0x%x, highlighting 0x%x %s</h3>" %
31521cb0ef41Sopenharmony_ci            (start_address, end_address, highlight_address, expand))
31531cb0ef41Sopenharmony_ci    f.write('<div class="code">')
31541cb0ef41Sopenharmony_ci    f.write("<table class=\"codedump\">");
31551cb0ef41Sopenharmony_ci    for i in range(len(lines)):
31561cb0ef41Sopenharmony_ci      line = lines[i]
31571cb0ef41Sopenharmony_ci      next_address = count
31581cb0ef41Sopenharmony_ci      if i + 1 < len(lines):
31591cb0ef41Sopenharmony_ci        next_line = lines[i + 1]
31601cb0ef41Sopenharmony_ci        next_address = next_line[0]
31611cb0ef41Sopenharmony_ci      self.format_disasm_line(
31621cb0ef41Sopenharmony_ci          f, start_address, line, next_address, highlight_address)
31631cb0ef41Sopenharmony_ci    f.write("</table>")
31641cb0ef41Sopenharmony_ci    f.write("</div>")
31651cb0ef41Sopenharmony_ci    return
31661cb0ef41Sopenharmony_ci
31671cb0ef41Sopenharmony_ci  def annotate_disasm_addresses(self, line):
31681cb0ef41Sopenharmony_ci    extra = []
31691cb0ef41Sopenharmony_ci    for m in ADDRESS_RE.finditer(line):
31701cb0ef41Sopenharmony_ci      maybe_address = int(m.group(0), 16)
31711cb0ef41Sopenharmony_ci      formatted_address = self.format_address(maybe_address, m.group(0))
31721cb0ef41Sopenharmony_ci      line = line.replace(m.group(0), formatted_address)
31731cb0ef41Sopenharmony_ci      object_info = self.padawan.SenseObject(maybe_address)
31741cb0ef41Sopenharmony_ci      if not object_info:
31751cb0ef41Sopenharmony_ci        continue
31761cb0ef41Sopenharmony_ci        extra.append(html.escape(str(object_info)))
31771cb0ef41Sopenharmony_ci    if len(extra) == 0:
31781cb0ef41Sopenharmony_ci      return line
31791cb0ef41Sopenharmony_ci    return ("%s <span class=disasmcomment>;; %s</span>" %
31801cb0ef41Sopenharmony_ci            (line, ", ".join(extra)))
31811cb0ef41Sopenharmony_ci
31821cb0ef41Sopenharmony_ci  def format_disasm_line(
31831cb0ef41Sopenharmony_ci      self, f, start, line, next_address, highlight_address):
31841cb0ef41Sopenharmony_ci    line_address = start + line[0]
31851cb0ef41Sopenharmony_ci    address_fmt = "  <td>%s</td>"
31861cb0ef41Sopenharmony_ci    if line_address == highlight_address:
31871cb0ef41Sopenharmony_ci      f.write("<tr class=highlight-line>")
31881cb0ef41Sopenharmony_ci      address_fmt = "  <td><a id=highlight>%s</a></td>"
31891cb0ef41Sopenharmony_ci    elif (line_address < highlight_address and
31901cb0ef41Sopenharmony_ci          highlight_address < next_address + start):
31911cb0ef41Sopenharmony_ci      f.write("<tr class=inexact-highlight-line>")
31921cb0ef41Sopenharmony_ci      address_fmt = "  <td><a id=highlight>%s</a></td>"
31931cb0ef41Sopenharmony_ci    else:
31941cb0ef41Sopenharmony_ci      f.write("<tr>")
31951cb0ef41Sopenharmony_ci    num_bytes = next_address - line[0]
31961cb0ef41Sopenharmony_ci    stack_slot = self.heap.stack_map.get(line_address)
31971cb0ef41Sopenharmony_ci    marker = ""
31981cb0ef41Sopenharmony_ci    if stack_slot:
31991cb0ef41Sopenharmony_ci      marker = "=>"
32001cb0ef41Sopenharmony_ci
32011cb0ef41Sopenharmony_ci    code = line[1]
32021cb0ef41Sopenharmony_ci
32031cb0ef41Sopenharmony_ci    # Some disassemblers insert spaces between each byte,
32041cb0ef41Sopenharmony_ci    # while some do not.
32051cb0ef41Sopenharmony_ci    if code[2] == " ":
32061cb0ef41Sopenharmony_ci      op_offset = 3 * num_bytes - 1
32071cb0ef41Sopenharmony_ci    else:
32081cb0ef41Sopenharmony_ci      op_offset = 2 * num_bytes
32091cb0ef41Sopenharmony_ci
32101cb0ef41Sopenharmony_ci    # Compute the actual call target which the disassembler is too stupid
32111cb0ef41Sopenharmony_ci    # to figure out (it adds the call offset to the disassembly offset rather
32121cb0ef41Sopenharmony_ci    # than the absolute instruction address).
32131cb0ef41Sopenharmony_ci    if self.heap.reader.arch == MD_CPU_ARCHITECTURE_X86:
32141cb0ef41Sopenharmony_ci      if code.startswith("e8"):
32151cb0ef41Sopenharmony_ci        words = code.split()
32161cb0ef41Sopenharmony_ci        if len(words) > 6 and words[5] == "call":
32171cb0ef41Sopenharmony_ci          offset = int(words[4] + words[3] + words[2] + words[1], 16)
32181cb0ef41Sopenharmony_ci          target = (line_address + offset + 5) & 0xFFFFFFFF
32191cb0ef41Sopenharmony_ci          code = code.replace(words[6], "0x%08x" % target)
32201cb0ef41Sopenharmony_ci    # TODO(jkummerow): port this hack to ARM and x64.
32211cb0ef41Sopenharmony_ci
32221cb0ef41Sopenharmony_ci    opcodes = code[:op_offset]
32231cb0ef41Sopenharmony_ci    code = self.annotate_disasm_addresses(code[op_offset:])
32241cb0ef41Sopenharmony_ci    f.write("  <td>")
32251cb0ef41Sopenharmony_ci    self.output_comment_box(f, "codel-", line_address)
32261cb0ef41Sopenharmony_ci    f.write("</td>")
32271cb0ef41Sopenharmony_ci    f.write(address_fmt % marker)
32281cb0ef41Sopenharmony_ci    f.write("  ")
32291cb0ef41Sopenharmony_ci    self.td_from_address(f, line_address)
32301cb0ef41Sopenharmony_ci    f.write(self.format_address(line_address))
32311cb0ef41Sopenharmony_ci    f.write(" (+0x%x)</td>" % line[0])
32321cb0ef41Sopenharmony_ci    f.write("<td>:&nbsp;%s&nbsp;</td>" % opcodes)
32331cb0ef41Sopenharmony_ci    f.write("<td>%s</td>" % code)
32341cb0ef41Sopenharmony_ci    f.write("</tr>")
32351cb0ef41Sopenharmony_ci
32361cb0ef41Sopenharmony_ci  def output_comment_box(self, f, prefix, address):
32371cb0ef41Sopenharmony_ci    comment = self.comments.get_comment(address)
32381cb0ef41Sopenharmony_ci    value = ""
32391cb0ef41Sopenharmony_ci    if comment:
32401cb0ef41Sopenharmony_ci      value = " value=\"%s\"" % html.escape(comment)
32411cb0ef41Sopenharmony_ci    f.write("<input type=text class=ci "
32421cb0ef41Sopenharmony_ci            "id=%s-address-0x%s onchange=c()%s>" %
32431cb0ef41Sopenharmony_ci            (prefix,
32441cb0ef41Sopenharmony_ci             self.reader.FormatIntPtr(address),
32451cb0ef41Sopenharmony_ci             value))
32461cb0ef41Sopenharmony_ci
32471cb0ef41Sopenharmony_ci  MAX_FOUND_RESULTS = 100
32481cb0ef41Sopenharmony_ci
32491cb0ef41Sopenharmony_ci  def output_find_results(self, f, results):
32501cb0ef41Sopenharmony_ci    f.write("Addresses")
32511cb0ef41Sopenharmony_ci    toomany = len(results) > self.MAX_FOUND_RESULTS
32521cb0ef41Sopenharmony_ci    if toomany:
32531cb0ef41Sopenharmony_ci      f.write("(found %i results, displaying only first %i)" %
32541cb0ef41Sopenharmony_ci              (len(results), self.MAX_FOUND_RESULTS))
32551cb0ef41Sopenharmony_ci    f.write(": ")
32561cb0ef41Sopenharmony_ci    results = sorted(results)
32571cb0ef41Sopenharmony_ci    results = results[:min(len(results), self.MAX_FOUND_RESULTS)]
32581cb0ef41Sopenharmony_ci    for address in results:
32591cb0ef41Sopenharmony_ci      f.write("<span %s>%s</span>" %
32601cb0ef41Sopenharmony_ci              (self.comments.get_style_class_string(address),
32611cb0ef41Sopenharmony_ci               self.format_address(address)))
32621cb0ef41Sopenharmony_ci    if toomany:
32631cb0ef41Sopenharmony_ci      f.write("...")
32641cb0ef41Sopenharmony_ci
32651cb0ef41Sopenharmony_ci
32661cb0ef41Sopenharmony_ci  def output_page_info(self, f, page_kind, page_address, my_page_address):
32671cb0ef41Sopenharmony_ci    if my_page_address == page_address and page_address != 0:
32681cb0ef41Sopenharmony_ci      f.write("Marked first %s page." % page_kind)
32691cb0ef41Sopenharmony_ci    else:
32701cb0ef41Sopenharmony_ci      f.write("<span id=\"%spage\" style=\"display:none\">" % page_kind)
32711cb0ef41Sopenharmony_ci      f.write("Marked first %s page." % page_kind)
32721cb0ef41Sopenharmony_ci      f.write("</span>\n")
32731cb0ef41Sopenharmony_ci      f.write("<button onclick=\"onpage('%spage', '0x%x')\">" %
32741cb0ef41Sopenharmony_ci              (page_kind, my_page_address))
32751cb0ef41Sopenharmony_ci      f.write("Mark as first %s page</button>" % page_kind)
32761cb0ef41Sopenharmony_ci    return
32771cb0ef41Sopenharmony_ci
32781cb0ef41Sopenharmony_ci  def output_search_res(self, f, straddress):
32791cb0ef41Sopenharmony_ci    try:
32801cb0ef41Sopenharmony_ci      self.output_header(f)
32811cb0ef41Sopenharmony_ci      f.write("<h3>Search results for %s</h3>" % straddress)
32821cb0ef41Sopenharmony_ci
32831cb0ef41Sopenharmony_ci      address = int(straddress, 0)
32841cb0ef41Sopenharmony_ci
32851cb0ef41Sopenharmony_ci      f.write("Comment: ")
32861cb0ef41Sopenharmony_ci      self.output_comment_box(f, "search-", address)
32871cb0ef41Sopenharmony_ci      f.write("<br>")
32881cb0ef41Sopenharmony_ci
32891cb0ef41Sopenharmony_ci      page_address = address & ~self.heap.PageAlignmentMask()
32901cb0ef41Sopenharmony_ci
32911cb0ef41Sopenharmony_ci      f.write("Page info: ")
32921cb0ef41Sopenharmony_ci      self.output_page_info(f, "old", self.padawan.known_first_old_page, \
32931cb0ef41Sopenharmony_ci                            page_address)
32941cb0ef41Sopenharmony_ci      self.output_page_info(f, "map", self.padawan.known_first_map_page, \
32951cb0ef41Sopenharmony_ci                            page_address)
32961cb0ef41Sopenharmony_ci
32971cb0ef41Sopenharmony_ci      if not self.reader.IsValidAddress(address):
32981cb0ef41Sopenharmony_ci        f.write("<h3>The contents at address %s not found in the dump.</h3>" % \
32991cb0ef41Sopenharmony_ci                straddress)
33001cb0ef41Sopenharmony_ci      else:
33011cb0ef41Sopenharmony_ci        # Print as words
33021cb0ef41Sopenharmony_ci        self.output_words(f, address - 8, address + 32, address, "Dump",
33031cb0ef41Sopenharmony_ci                          self.heap.MachinePointerSize())
33041cb0ef41Sopenharmony_ci
33051cb0ef41Sopenharmony_ci        if self.heap.IsPointerCompressed():
33061cb0ef41Sopenharmony_ci          self.output_words(f, address - 8, address + 32, address,
33071cb0ef41Sopenharmony_ci                            "Tagged Dump", self.heap.TaggedPointerSize())
33081cb0ef41Sopenharmony_ci
33091cb0ef41Sopenharmony_ci        # Print as ASCII
33101cb0ef41Sopenharmony_ci        f.write("<hr>")
33111cb0ef41Sopenharmony_ci        self.output_ascii(f, address, address + 256, address)
33121cb0ef41Sopenharmony_ci
33131cb0ef41Sopenharmony_ci        # Print as code
33141cb0ef41Sopenharmony_ci        f.write("<hr>")
33151cb0ef41Sopenharmony_ci        self.output_disasm_range(f, address - 16, address + 16, address, True)
33161cb0ef41Sopenharmony_ci
33171cb0ef41Sopenharmony_ci      aligned_res, unaligned_res = self.reader.FindWordList(address)
33181cb0ef41Sopenharmony_ci
33191cb0ef41Sopenharmony_ci      if len(aligned_res) > 0:
33201cb0ef41Sopenharmony_ci        f.write("<h3>Occurrences of 0x%x at aligned addresses</h3>" %
33211cb0ef41Sopenharmony_ci                address)
33221cb0ef41Sopenharmony_ci        self.output_find_results(f, aligned_res)
33231cb0ef41Sopenharmony_ci
33241cb0ef41Sopenharmony_ci      if len(unaligned_res) > 0:
33251cb0ef41Sopenharmony_ci        f.write("<h3>Occurrences of 0x%x at unaligned addresses</h3>" % \
33261cb0ef41Sopenharmony_ci                address)
33271cb0ef41Sopenharmony_ci        self.output_find_results(f, unaligned_res)
33281cb0ef41Sopenharmony_ci
33291cb0ef41Sopenharmony_ci      if len(aligned_res) + len(unaligned_res) == 0:
33301cb0ef41Sopenharmony_ci        f.write("<h3>No occurrences of 0x%x found in the dump</h3>" % address)
33311cb0ef41Sopenharmony_ci
33321cb0ef41Sopenharmony_ci      self.output_footer(f)
33331cb0ef41Sopenharmony_ci
33341cb0ef41Sopenharmony_ci    except ValueError:
33351cb0ef41Sopenharmony_ci      f.write("<h3>Unrecognized address format \"%s\".</h3>" % straddress)
33361cb0ef41Sopenharmony_ci    return
33371cb0ef41Sopenharmony_ci
33381cb0ef41Sopenharmony_ci  def output_disasm_pc(self, f):
33391cb0ef41Sopenharmony_ci    address = self.reader.ExceptionIP()
33401cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(address):
33411cb0ef41Sopenharmony_ci      return
33421cb0ef41Sopenharmony_ci    self.output_disasm_range(f, address - 16, address + 16, address, True)
33431cb0ef41Sopenharmony_ci
33441cb0ef41Sopenharmony_ci
33451cb0ef41Sopenharmony_ciWEB_DUMPS_HEADER = """
33461cb0ef41Sopenharmony_ci<!DOCTYPE html>
33471cb0ef41Sopenharmony_ci<html>
33481cb0ef41Sopenharmony_ci<head>
33491cb0ef41Sopenharmony_ci<meta content="text/html; charset=utf-8" http-equiv="content-type">
33501cb0ef41Sopenharmony_ci<style media="screen" type="text/css">
33511cb0ef41Sopenharmony_ci
33521cb0ef41Sopenharmony_ci.dumplist {
33531cb0ef41Sopenharmony_ci  border-collapse : collapse;
33541cb0ef41Sopenharmony_ci  border-spacing : 0px;
33551cb0ef41Sopenharmony_ci  font-family: monospace;
33561cb0ef41Sopenharmony_ci}
33571cb0ef41Sopenharmony_ci
33581cb0ef41Sopenharmony_ci.dumpcomments {
33591cb0ef41Sopenharmony_ci  border : 1px solid LightGray;
33601cb0ef41Sopenharmony_ci  width : 32em;
33611cb0ef41Sopenharmony_ci}
33621cb0ef41Sopenharmony_ci
33631cb0ef41Sopenharmony_ci</style>
33641cb0ef41Sopenharmony_ci
33651cb0ef41Sopenharmony_ci<script type="application/javascript">
33661cb0ef41Sopenharmony_ci
33671cb0ef41Sopenharmony_civar dump_str = "dump-";
33681cb0ef41Sopenharmony_civar dump_len = dump_str.length;
33691cb0ef41Sopenharmony_ci
33701cb0ef41Sopenharmony_cifunction dump_comment() {
33711cb0ef41Sopenharmony_ci  var s = event.srcElement.id;
33721cb0ef41Sopenharmony_ci  var index = s.indexOf(dump_str);
33731cb0ef41Sopenharmony_ci  if (index >= 0) {
33741cb0ef41Sopenharmony_ci    send_dump_desc(s.substring(index + dump_len), event.srcElement.value);
33751cb0ef41Sopenharmony_ci  }
33761cb0ef41Sopenharmony_ci}
33771cb0ef41Sopenharmony_ci
33781cb0ef41Sopenharmony_cifunction send_dump_desc(name, desc) {
33791cb0ef41Sopenharmony_ci  xmlhttp = new XMLHttpRequest();
33801cb0ef41Sopenharmony_ci  name = encodeURIComponent(name)
33811cb0ef41Sopenharmony_ci  desc = encodeURIComponent(desc)
33821cb0ef41Sopenharmony_ci  xmlhttp.open("GET",
33831cb0ef41Sopenharmony_ci      "setdumpdesc?dump=" + name +
33841cb0ef41Sopenharmony_ci      "&description=" + desc, true);
33851cb0ef41Sopenharmony_ci  xmlhttp.send();
33861cb0ef41Sopenharmony_ci}
33871cb0ef41Sopenharmony_ci
33881cb0ef41Sopenharmony_ci</script>
33891cb0ef41Sopenharmony_ci
33901cb0ef41Sopenharmony_ci<title>Dump list</title>
33911cb0ef41Sopenharmony_ci</head>
33921cb0ef41Sopenharmony_ci
33931cb0ef41Sopenharmony_ci<body>
33941cb0ef41Sopenharmony_ci"""
33951cb0ef41Sopenharmony_ci
33961cb0ef41Sopenharmony_ciWEB_DUMPS_FOOTER = """
33971cb0ef41Sopenharmony_ci</body>
33981cb0ef41Sopenharmony_ci</html>
33991cb0ef41Sopenharmony_ci"""
34001cb0ef41Sopenharmony_ci
34011cb0ef41Sopenharmony_ciDUMP_FILE_RE = re.compile(r"[-_0-9a-zA-Z][-\._0-9a-zA-Z]*\.dmp$")
34021cb0ef41Sopenharmony_ci
34031cb0ef41Sopenharmony_ci
34041cb0ef41Sopenharmony_ciclass InspectionWebServer(http_server.HTTPServer):
34051cb0ef41Sopenharmony_ci
34061cb0ef41Sopenharmony_ci  def __init__(self, port_number, switches, minidump_name):
34071cb0ef41Sopenharmony_ci    super().__init__(('localhost', port_number), InspectionWebHandler)
34081cb0ef41Sopenharmony_ci    splitpath = os.path.split(minidump_name)
34091cb0ef41Sopenharmony_ci    self.dumppath = splitpath[0]
34101cb0ef41Sopenharmony_ci    self.dumpfilename = splitpath[1]
34111cb0ef41Sopenharmony_ci    self.default_formatter = InspectionWebFormatter(
34121cb0ef41Sopenharmony_ci        switches, minidump_name, self)
34131cb0ef41Sopenharmony_ci    self.formatters = { self.dumpfilename : self.default_formatter }
34141cb0ef41Sopenharmony_ci    self.switches = switches
34151cb0ef41Sopenharmony_ci
34161cb0ef41Sopenharmony_ci  def output_dump_desc_field(self, f, name):
34171cb0ef41Sopenharmony_ci    try:
34181cb0ef41Sopenharmony_ci      descfile = open(os.path.join(self.dumppath, name + ".desc"), "r")
34191cb0ef41Sopenharmony_ci      desc = descfile.readline()
34201cb0ef41Sopenharmony_ci      descfile.close()
34211cb0ef41Sopenharmony_ci    except IOError:
34221cb0ef41Sopenharmony_ci      desc = ""
34231cb0ef41Sopenharmony_ci    f.write("<input type=\"text\" class=\"dumpcomments\" "
34241cb0ef41Sopenharmony_ci            "id=\"dump-%s\" onchange=\"dump_comment()\" value=\"%s\">\n" %
34251cb0ef41Sopenharmony_ci            (html.escape(name), desc))
34261cb0ef41Sopenharmony_ci
34271cb0ef41Sopenharmony_ci  def set_dump_desc(self, name, description):
34281cb0ef41Sopenharmony_ci    if not DUMP_FILE_RE.match(name):
34291cb0ef41Sopenharmony_ci      return False
34301cb0ef41Sopenharmony_ci    fname = os.path.join(self.dumppath, name)
34311cb0ef41Sopenharmony_ci    if not os.path.isfile(fname):
34321cb0ef41Sopenharmony_ci      return False
34331cb0ef41Sopenharmony_ci    fname = fname + ".desc"
34341cb0ef41Sopenharmony_ci    descfile = open(fname, "w")
34351cb0ef41Sopenharmony_ci    descfile.write(description)
34361cb0ef41Sopenharmony_ci    descfile.close()
34371cb0ef41Sopenharmony_ci    return True
34381cb0ef41Sopenharmony_ci
34391cb0ef41Sopenharmony_ci  def get_dump_formatter(self, name):
34401cb0ef41Sopenharmony_ci    if name is None:
34411cb0ef41Sopenharmony_ci      return self.default_formatter
34421cb0ef41Sopenharmony_ci    else:
34431cb0ef41Sopenharmony_ci      if not DUMP_FILE_RE.match(name):
34441cb0ef41Sopenharmony_ci        raise WebParameterError("Invalid name '%s'" % name)
34451cb0ef41Sopenharmony_ci      formatter = self.formatters.get(name, None)
34461cb0ef41Sopenharmony_ci      if formatter is None:
34471cb0ef41Sopenharmony_ci        try:
34481cb0ef41Sopenharmony_ci          formatter = InspectionWebFormatter(
34491cb0ef41Sopenharmony_ci              self.switches, os.path.join(self.dumppath, name), self)
34501cb0ef41Sopenharmony_ci          self.formatters[name] = formatter
34511cb0ef41Sopenharmony_ci        except IOError:
34521cb0ef41Sopenharmony_ci          raise WebParameterError("Could not open dump '%s'" % name)
34531cb0ef41Sopenharmony_ci      return formatter
34541cb0ef41Sopenharmony_ci
34551cb0ef41Sopenharmony_ci  def output_dumps(self, f):
34561cb0ef41Sopenharmony_ci    f.write(WEB_DUMPS_HEADER)
34571cb0ef41Sopenharmony_ci    f.write("<h3>List of available dumps</h3>")
34581cb0ef41Sopenharmony_ci    f.write("<table class=\"dumplist\">\n")
34591cb0ef41Sopenharmony_ci    f.write("<thead><tr>")
34601cb0ef41Sopenharmony_ci    f.write("<th>Name</th>")
34611cb0ef41Sopenharmony_ci    f.write("<th>File time</th>")
34621cb0ef41Sopenharmony_ci    f.write("<th>Comment</th>")
34631cb0ef41Sopenharmony_ci    f.write("</tr></thead>")
34641cb0ef41Sopenharmony_ci    dumps_by_time = {}
34651cb0ef41Sopenharmony_ci    for fname in os.listdir(self.dumppath):
34661cb0ef41Sopenharmony_ci      if DUMP_FILE_RE.match(fname):
34671cb0ef41Sopenharmony_ci        mtime = os.stat(os.path.join(self.dumppath, fname)).st_mtime
34681cb0ef41Sopenharmony_ci        fnames = dumps_by_time.get(mtime, [])
34691cb0ef41Sopenharmony_ci        fnames.append(fname)
34701cb0ef41Sopenharmony_ci        dumps_by_time[mtime] = fnames
34711cb0ef41Sopenharmony_ci
34721cb0ef41Sopenharmony_ci    for mtime in sorted(dumps_by_time, reverse=True):
34731cb0ef41Sopenharmony_ci      fnames = dumps_by_time[mtime]
34741cb0ef41Sopenharmony_ci      for fname in fnames:
34751cb0ef41Sopenharmony_ci        f.write("<tr>\n")
34761cb0ef41Sopenharmony_ci        f.write("<td><a href=\"summary.html?%s\">%s</a></td>\n" %
34771cb0ef41Sopenharmony_ci                ((urllib.parse.urlencode({'dump': fname}), fname)))
34781cb0ef41Sopenharmony_ci        f.write("<td>&nbsp;&nbsp;&nbsp;")
34791cb0ef41Sopenharmony_ci        f.write(datetime.datetime.fromtimestamp(mtime))
34801cb0ef41Sopenharmony_ci        f.write("</td>")
34811cb0ef41Sopenharmony_ci        f.write("<td>&nbsp;&nbsp;&nbsp;")
34821cb0ef41Sopenharmony_ci        self.output_dump_desc_field(f, fname)
34831cb0ef41Sopenharmony_ci        f.write("</td>")
34841cb0ef41Sopenharmony_ci        f.write("</tr>\n")
34851cb0ef41Sopenharmony_ci    f.write("</table>\n")
34861cb0ef41Sopenharmony_ci    f.write(WEB_DUMPS_FOOTER)
34871cb0ef41Sopenharmony_ci    return
34881cb0ef41Sopenharmony_ci
34891cb0ef41Sopenharmony_ciclass InspectionShell(cmd.Cmd):
34901cb0ef41Sopenharmony_ci  def __init__(self, reader, heap):
34911cb0ef41Sopenharmony_ci    cmd.Cmd.__init__(self)
34921cb0ef41Sopenharmony_ci    self.reader = reader
34931cb0ef41Sopenharmony_ci    self.heap = heap
34941cb0ef41Sopenharmony_ci    self.padawan = InspectionPadawan(reader, heap)
34951cb0ef41Sopenharmony_ci    self.prompt = "(grok) "
34961cb0ef41Sopenharmony_ci
34971cb0ef41Sopenharmony_ci    self.dd_start = 0
34981cb0ef41Sopenharmony_ci    self.dd_num = 0x10
34991cb0ef41Sopenharmony_ci    self.u_start = 0
35001cb0ef41Sopenharmony_ci    self.u_num = 0
35011cb0ef41Sopenharmony_ci
35021cb0ef41Sopenharmony_ci  def EvalExpression(self, expr):
35031cb0ef41Sopenharmony_ci    # Auto convert hex numbers to a python compatible format
35041cb0ef41Sopenharmony_ci    if expr[:2] == "00":
35051cb0ef41Sopenharmony_ci      expr = "0x"+expr
35061cb0ef41Sopenharmony_ci    result = None
35071cb0ef41Sopenharmony_ci    try:
35081cb0ef41Sopenharmony_ci      # Ugly hack to patch in register values.
35091cb0ef41Sopenharmony_ci      registers = [register
35101cb0ef41Sopenharmony_ci                   for register,value in self.reader.ContextDescriptor().fields]
35111cb0ef41Sopenharmony_ci      registers.sort(key=lambda r: len(r))
35121cb0ef41Sopenharmony_ci      registers.reverse()
35131cb0ef41Sopenharmony_ci      for register in registers:
35141cb0ef41Sopenharmony_ci        expr = expr.replace("$"+register, str(self.reader.Register(register)))
35151cb0ef41Sopenharmony_ci      result = eval(expr)
35161cb0ef41Sopenharmony_ci    except Exception as e:
35171cb0ef41Sopenharmony_ci      print("**** Could not evaluate '%s': %s" % (expr, e))
35181cb0ef41Sopenharmony_ci      raise e
35191cb0ef41Sopenharmony_ci    return result
35201cb0ef41Sopenharmony_ci
35211cb0ef41Sopenharmony_ci  def ParseAddressExpr(self, expr):
35221cb0ef41Sopenharmony_ci    address = 0;
35231cb0ef41Sopenharmony_ci    try:
35241cb0ef41Sopenharmony_ci      result = self.EvalExpression(expr)
35251cb0ef41Sopenharmony_ci    except:
35261cb0ef41Sopenharmony_ci      return 0
35271cb0ef41Sopenharmony_ci    try:
35281cb0ef41Sopenharmony_ci      address = int(result)
35291cb0ef41Sopenharmony_ci    except Exception as e:
35301cb0ef41Sopenharmony_ci      print("**** Could not convert '%s' => %s to valid address: %s" % (
35311cb0ef41Sopenharmony_ci          expr, result , e))
35321cb0ef41Sopenharmony_ci    return address
35331cb0ef41Sopenharmony_ci
35341cb0ef41Sopenharmony_ci  def do_help(self, cmd=None):
35351cb0ef41Sopenharmony_ci    if len(cmd) == 0:
35361cb0ef41Sopenharmony_ci      print("Available commands")
35371cb0ef41Sopenharmony_ci      print("=" * 79)
35381cb0ef41Sopenharmony_ci      prefix = "do_"
35391cb0ef41Sopenharmony_ci      methods = inspect.getmembers(InspectionShell, predicate=inspect.ismethod)
35401cb0ef41Sopenharmony_ci      for name,method in methods:
35411cb0ef41Sopenharmony_ci        if not name.startswith(prefix): continue
35421cb0ef41Sopenharmony_ci        doc = inspect.getdoc(method)
35431cb0ef41Sopenharmony_ci        if not doc: continue
35441cb0ef41Sopenharmony_ci        name = prefix.join(name.split(prefix)[1:])
35451cb0ef41Sopenharmony_ci        description = doc.splitlines()[0]
35461cb0ef41Sopenharmony_ci        print((name + ": ").ljust(16) + description)
35471cb0ef41Sopenharmony_ci      print("=" * 79)
35481cb0ef41Sopenharmony_ci    else:
35491cb0ef41Sopenharmony_ci      return super(InspectionShell, self).do_help(cmd)
35501cb0ef41Sopenharmony_ci
35511cb0ef41Sopenharmony_ci  def do_p(self, cmd):
35521cb0ef41Sopenharmony_ci    """ see print """
35531cb0ef41Sopenharmony_ci    return self.do_print(cmd)
35541cb0ef41Sopenharmony_ci
35551cb0ef41Sopenharmony_ci  def do_print(self, cmd):
35561cb0ef41Sopenharmony_ci    """
35571cb0ef41Sopenharmony_ci    Evaluate an arbitrary python command.
35581cb0ef41Sopenharmony_ci    """
35591cb0ef41Sopenharmony_ci    try:
35601cb0ef41Sopenharmony_ci      print(self.EvalExpression(cmd))
35611cb0ef41Sopenharmony_ci    except:
35621cb0ef41Sopenharmony_ci      pass
35631cb0ef41Sopenharmony_ci
35641cb0ef41Sopenharmony_ci  def do_da(self, address):
35651cb0ef41Sopenharmony_ci    """ see display_ascii"""
35661cb0ef41Sopenharmony_ci    return self.do_display_ascii(address)
35671cb0ef41Sopenharmony_ci
35681cb0ef41Sopenharmony_ci  def do_display_ascii(self, address):
35691cb0ef41Sopenharmony_ci    """
35701cb0ef41Sopenharmony_ci     Print ASCII string starting at specified address.
35711cb0ef41Sopenharmony_ci    """
35721cb0ef41Sopenharmony_ci    address = self.ParseAddressExpr(address)
35731cb0ef41Sopenharmony_ci    string = self.reader.ReadAsciiString(address)
35741cb0ef41Sopenharmony_ci    if string == "":
35751cb0ef41Sopenharmony_ci      print("Not an ASCII string at %s" % self.reader.FormatIntPtr(address))
35761cb0ef41Sopenharmony_ci    else:
35771cb0ef41Sopenharmony_ci      print("%s\n" % string)
35781cb0ef41Sopenharmony_ci
35791cb0ef41Sopenharmony_ci  def do_dsa(self, address):
35801cb0ef41Sopenharmony_ci    """ see display_stack_ascii"""
35811cb0ef41Sopenharmony_ci    return self.do_display_stack_ascii(address)
35821cb0ef41Sopenharmony_ci
35831cb0ef41Sopenharmony_ci  def do_display_stack_ascii(self, address):
35841cb0ef41Sopenharmony_ci    """
35851cb0ef41Sopenharmony_ci    Print ASCII stack error message.
35861cb0ef41Sopenharmony_ci    """
35871cb0ef41Sopenharmony_ci    if self.reader.exception is None:
35881cb0ef41Sopenharmony_ci      print("Minidump has no exception info")
35891cb0ef41Sopenharmony_ci      return
35901cb0ef41Sopenharmony_ci    if len(address) == 0:
35911cb0ef41Sopenharmony_ci      address = None
35921cb0ef41Sopenharmony_ci    else:
35931cb0ef41Sopenharmony_ci      address = self.ParseAddressExpr(address)
35941cb0ef41Sopenharmony_ci    self.padawan.PrintStackTraceMessage(address)
35951cb0ef41Sopenharmony_ci
35961cb0ef41Sopenharmony_ci  def do_dd(self, args):
35971cb0ef41Sopenharmony_ci    """
35981cb0ef41Sopenharmony_ci     Interpret memory in the given region [address, address + num * word_size)
35991cb0ef41Sopenharmony_ci
36001cb0ef41Sopenharmony_ci     (if available) as a sequence of words. Automatic alignment is not performed.
36011cb0ef41Sopenharmony_ci     If the num is not specified, a default value of 16 words is usif not self.Is
36021cb0ef41Sopenharmony_ci     If no address is given, dd continues printing at the next word.
36031cb0ef41Sopenharmony_ci
36041cb0ef41Sopenharmony_ci     Synopsis: dd 0x<address>|$register [0x<num>]
36051cb0ef41Sopenharmony_ci    """
36061cb0ef41Sopenharmony_ci    if len(args) != 0:
36071cb0ef41Sopenharmony_ci      args = args.split(' ')
36081cb0ef41Sopenharmony_ci      self.dd_start = self.ParseAddressExpr(args[0])
36091cb0ef41Sopenharmony_ci      self.dd_num = int(args[1], 16) if len(args) > 1 else 0x10
36101cb0ef41Sopenharmony_ci    else:
36111cb0ef41Sopenharmony_ci      self.dd_start += self.dd_num * self.reader.MachinePointerSize()
36121cb0ef41Sopenharmony_ci    if not self.reader.IsAlignedAddress(self.dd_start):
36131cb0ef41Sopenharmony_ci      print("Warning: Dumping un-aligned memory, is this what you had in mind?")
36141cb0ef41Sopenharmony_ci    end = self.dd_start + self.reader.MachinePointerSize() * self.dd_num
36151cb0ef41Sopenharmony_ci    self.padawan.InterpretMemory(self.dd_start, end)
36161cb0ef41Sopenharmony_ci
36171cb0ef41Sopenharmony_ci  def do_do(self, address):
36181cb0ef41Sopenharmony_ci    """ see display_object """
36191cb0ef41Sopenharmony_ci    return self.do_display_object(address)
36201cb0ef41Sopenharmony_ci
36211cb0ef41Sopenharmony_ci  def do_display_object(self, address):
36221cb0ef41Sopenharmony_ci    """
36231cb0ef41Sopenharmony_ci     Interpret memory at the given address as a V8 object.
36241cb0ef41Sopenharmony_ci
36251cb0ef41Sopenharmony_ci     Automatic alignment makes sure that you can pass tagged as well as
36261cb0ef41Sopenharmony_ci     un-tagged addresses.
36271cb0ef41Sopenharmony_ci    """
36281cb0ef41Sopenharmony_ci    address = self.ParseAddressExpr(address)
36291cb0ef41Sopenharmony_ci    if self.reader.IsAlignedAddress(address):
36301cb0ef41Sopenharmony_ci      address = address + 1
36311cb0ef41Sopenharmony_ci    elif not self.heap.IsTaggedObjectAddress(address):
36321cb0ef41Sopenharmony_ci      print("Address doesn't look like a valid pointer!")
36331cb0ef41Sopenharmony_ci      return
36341cb0ef41Sopenharmony_ci    heap_object = self.padawan.SenseObject(address)
36351cb0ef41Sopenharmony_ci    if heap_object:
36361cb0ef41Sopenharmony_ci      heap_object.Print(Printer())
36371cb0ef41Sopenharmony_ci    else:
36381cb0ef41Sopenharmony_ci      print("Address cannot be interpreted as object!")
36391cb0ef41Sopenharmony_ci
36401cb0ef41Sopenharmony_ci  def do_dso(self, args):
36411cb0ef41Sopenharmony_ci    """ see display_stack_objects """
36421cb0ef41Sopenharmony_ci    return self.do_display_stack_objects(args)
36431cb0ef41Sopenharmony_ci
36441cb0ef41Sopenharmony_ci  def do_display_stack_objects(self, args):
36451cb0ef41Sopenharmony_ci    """
36461cb0ef41Sopenharmony_ci    Find and Print object pointers in the given range.
36471cb0ef41Sopenharmony_ci
36481cb0ef41Sopenharmony_ci    Print all possible object pointers that are on the stack or in the given
36491cb0ef41Sopenharmony_ci    address range.
36501cb0ef41Sopenharmony_ci
36511cb0ef41Sopenharmony_ci    Usage: dso [START_ADDR,[END_ADDR]]
36521cb0ef41Sopenharmony_ci    """
36531cb0ef41Sopenharmony_ci    start = self.reader.StackTop()
36541cb0ef41Sopenharmony_ci    end = self.reader.StackBottom()
36551cb0ef41Sopenharmony_ci    if len(args) != 0:
36561cb0ef41Sopenharmony_ci      args = args.split(' ')
36571cb0ef41Sopenharmony_ci      start = self.ParseAddressExpr(args[0])
36581cb0ef41Sopenharmony_ci      end = self.ParseAddressExpr(args[1]) if len(args) > 1 else end
36591cb0ef41Sopenharmony_ci    objects = self.heap.FindObjectPointers(start, end)
36601cb0ef41Sopenharmony_ci    for address in objects:
36611cb0ef41Sopenharmony_ci      heap_object = self.padawan.SenseObject(address)
36621cb0ef41Sopenharmony_ci      info = ""
36631cb0ef41Sopenharmony_ci      if heap_object:
36641cb0ef41Sopenharmony_ci        info = str(heap_object)
36651cb0ef41Sopenharmony_ci      print("%s %s" % (self.padawan.FormatIntPtr(address), info))
36661cb0ef41Sopenharmony_ci
36671cb0ef41Sopenharmony_ci  def do_do_desc(self, address):
36681cb0ef41Sopenharmony_ci    """
36691cb0ef41Sopenharmony_ci      Print a descriptor array in a readable format.
36701cb0ef41Sopenharmony_ci    """
36711cb0ef41Sopenharmony_ci    start = self.ParseAddressExpr(address)
36721cb0ef41Sopenharmony_ci    if ((start & 1) == 1): start = start - 1
36731cb0ef41Sopenharmony_ci    DescriptorArray(FixedArray(self.heap, None, start)).Print(Printer())
36741cb0ef41Sopenharmony_ci
36751cb0ef41Sopenharmony_ci  def do_do_map(self, address):
36761cb0ef41Sopenharmony_ci    """
36771cb0ef41Sopenharmony_ci      Print a Map in a readable format.
36781cb0ef41Sopenharmony_ci    """
36791cb0ef41Sopenharmony_ci    start = self.ParseAddressExpr(address)
36801cb0ef41Sopenharmony_ci    if ((start & 1) == 1): start = start - 1
36811cb0ef41Sopenharmony_ci    Map(self.heap, None, start).Print(Printer())
36821cb0ef41Sopenharmony_ci
36831cb0ef41Sopenharmony_ci  def do_do_trans(self, address):
36841cb0ef41Sopenharmony_ci    """
36851cb0ef41Sopenharmony_ci      Print a transition array in a readable format.
36861cb0ef41Sopenharmony_ci    """
36871cb0ef41Sopenharmony_ci    start = self.ParseAddressExpr(address)
36881cb0ef41Sopenharmony_ci    if ((start & 1) == 1): start = start - 1
36891cb0ef41Sopenharmony_ci    TransitionArray(FixedArray(self.heap, None, start)).Print(Printer())
36901cb0ef41Sopenharmony_ci
36911cb0ef41Sopenharmony_ci  def do_dp(self, address):
36921cb0ef41Sopenharmony_ci    """ see display_page """
36931cb0ef41Sopenharmony_ci    return self.do_display_page(address)
36941cb0ef41Sopenharmony_ci
36951cb0ef41Sopenharmony_ci  def do_display_page(self, address):
36961cb0ef41Sopenharmony_ci    """
36971cb0ef41Sopenharmony_ci     Prints details about the V8 heap page of the given address.
36981cb0ef41Sopenharmony_ci
36991cb0ef41Sopenharmony_ci     Interpret memory at the given address as being on a V8 heap page
37001cb0ef41Sopenharmony_ci     and print information about the page header (if available).
37011cb0ef41Sopenharmony_ci    """
37021cb0ef41Sopenharmony_ci    address = self.ParseAddressExpr(address)
37031cb0ef41Sopenharmony_ci    page_address = address & ~self.heap.PageAlignmentMask()
37041cb0ef41Sopenharmony_ci    if self.reader.IsValidAddress(page_address):
37051cb0ef41Sopenharmony_ci      print("**** Not Implemented")
37061cb0ef41Sopenharmony_ci      return
37071cb0ef41Sopenharmony_ci    else:
37081cb0ef41Sopenharmony_ci      print("Page header is not available!")
37091cb0ef41Sopenharmony_ci
37101cb0ef41Sopenharmony_ci  def do_k(self, arguments):
37111cb0ef41Sopenharmony_ci    """
37121cb0ef41Sopenharmony_ci     Teach V8 heap layout information to the inspector.
37131cb0ef41Sopenharmony_ci
37141cb0ef41Sopenharmony_ci     This increases the amount of annotations the inspector can produce while
37151cb0ef41Sopenharmony_ci     dumping data. The first page of each heap space is of particular interest
37161cb0ef41Sopenharmony_ci     because it contains known objects that do not move.
37171cb0ef41Sopenharmony_ci    """
37181cb0ef41Sopenharmony_ci    self.padawan.PrintKnowledge()
37191cb0ef41Sopenharmony_ci
37201cb0ef41Sopenharmony_ci  def do_ko(self, address):
37211cb0ef41Sopenharmony_ci    """ see known_oldspace """
37221cb0ef41Sopenharmony_ci    return self.do_known_oldspace(address)
37231cb0ef41Sopenharmony_ci
37241cb0ef41Sopenharmony_ci  def do_known_oldspace(self, address):
37251cb0ef41Sopenharmony_ci    """
37261cb0ef41Sopenharmony_ci     Teach V8 heap layout information to the inspector.
37271cb0ef41Sopenharmony_ci
37281cb0ef41Sopenharmony_ci     Set the first old space page by passing any pointer into that page.
37291cb0ef41Sopenharmony_ci    """
37301cb0ef41Sopenharmony_ci    address = self.ParseAddressExpr(address)
37311cb0ef41Sopenharmony_ci    page_address = address & ~self.heap.PageAlignmentMask()
37321cb0ef41Sopenharmony_ci    self.padawan.known_first_old_page = page_address
37331cb0ef41Sopenharmony_ci
37341cb0ef41Sopenharmony_ci  def do_km(self, address):
37351cb0ef41Sopenharmony_ci    """ see known_map """
37361cb0ef41Sopenharmony_ci    return self.do_known_map(address)
37371cb0ef41Sopenharmony_ci
37381cb0ef41Sopenharmony_ci  def do_known_map(self, address):
37391cb0ef41Sopenharmony_ci    """
37401cb0ef41Sopenharmony_ci     Teach V8 heap layout information to the inspector.
37411cb0ef41Sopenharmony_ci
37421cb0ef41Sopenharmony_ci     Set the first map-space page by passing any pointer into that page.
37431cb0ef41Sopenharmony_ci    """
37441cb0ef41Sopenharmony_ci    address = self.ParseAddressExpr(address)
37451cb0ef41Sopenharmony_ci    page_address = address & ~self.heap.PageAlignmentMask()
37461cb0ef41Sopenharmony_ci    self.padawan.known_first_map_page = page_address
37471cb0ef41Sopenharmony_ci
37481cb0ef41Sopenharmony_ci  def do_list(self, smth):
37491cb0ef41Sopenharmony_ci    """
37501cb0ef41Sopenharmony_ci     List all available memory regions.
37511cb0ef41Sopenharmony_ci    """
37521cb0ef41Sopenharmony_ci    def print_region(reader, start, size, location):
37531cb0ef41Sopenharmony_ci      print("  %s - %s (%d bytes)" % (reader.FormatIntPtr(start),
37541cb0ef41Sopenharmony_ci                                      reader.FormatIntPtr(start + size),
37551cb0ef41Sopenharmony_ci                                      size))
37561cb0ef41Sopenharmony_ci    print("Available memory regions:")
37571cb0ef41Sopenharmony_ci    self.reader.ForEachMemoryRegion(print_region)
37581cb0ef41Sopenharmony_ci
37591cb0ef41Sopenharmony_ci  def do_lm(self, arg):
37601cb0ef41Sopenharmony_ci    """ see list_modules """
37611cb0ef41Sopenharmony_ci    return self.do_list_modules(arg)
37621cb0ef41Sopenharmony_ci
37631cb0ef41Sopenharmony_ci  def do_list_modules(self, arg):
37641cb0ef41Sopenharmony_ci    """
37651cb0ef41Sopenharmony_ci     List details for all loaded modules in the minidump.
37661cb0ef41Sopenharmony_ci
37671cb0ef41Sopenharmony_ci     An argument can be passed to limit the output to only those modules that
37681cb0ef41Sopenharmony_ci     contain the argument as a substring (case insensitive match).
37691cb0ef41Sopenharmony_ci    """
37701cb0ef41Sopenharmony_ci    for module in self.reader.module_list.modules:
37711cb0ef41Sopenharmony_ci      if arg:
37721cb0ef41Sopenharmony_ci        name = GetModuleName(self.reader, module).lower()
37731cb0ef41Sopenharmony_ci        if name.find(arg.lower()) >= 0:
37741cb0ef41Sopenharmony_ci          PrintModuleDetails(self.reader, module)
37751cb0ef41Sopenharmony_ci      else:
37761cb0ef41Sopenharmony_ci        PrintModuleDetails(self.reader, module)
37771cb0ef41Sopenharmony_ci    print()
37781cb0ef41Sopenharmony_ci
37791cb0ef41Sopenharmony_ci  def do_s(self, word):
37801cb0ef41Sopenharmony_ci    """ see search """
37811cb0ef41Sopenharmony_ci    return self.do_search(word)
37821cb0ef41Sopenharmony_ci
37831cb0ef41Sopenharmony_ci  def do_search(self, word):
37841cb0ef41Sopenharmony_ci    """
37851cb0ef41Sopenharmony_ci     Search for a given word in available memory regions.
37861cb0ef41Sopenharmony_ci
37871cb0ef41Sopenharmony_ci     The given word is expanded to full pointer size and searched at aligned
37881cb0ef41Sopenharmony_ci     as well as un-aligned memory locations. Use 'sa' to search aligned locations
37891cb0ef41Sopenharmony_ci     only.
37901cb0ef41Sopenharmony_ci    """
37911cb0ef41Sopenharmony_ci    try:
37921cb0ef41Sopenharmony_ci      word = self.ParseAddressExpr(word)
37931cb0ef41Sopenharmony_ci    except ValueError:
37941cb0ef41Sopenharmony_ci      print("Malformed word, prefix with '0x' to use hexadecimal format.")
37951cb0ef41Sopenharmony_ci      return
37961cb0ef41Sopenharmony_ci    print(
37971cb0ef41Sopenharmony_ci      "Searching for word %d/0x%s:" % (word, self.reader.FormatIntPtr(word)))
37981cb0ef41Sopenharmony_ci    self.reader.FindWord(word)
37991cb0ef41Sopenharmony_ci
38001cb0ef41Sopenharmony_ci  def do_sh(self, none):
38011cb0ef41Sopenharmony_ci    """
38021cb0ef41Sopenharmony_ci     Search for the V8 Heap object in all available memory regions.
38031cb0ef41Sopenharmony_ci
38041cb0ef41Sopenharmony_ci     You might get lucky and find this rare treasure full of invaluable
38051cb0ef41Sopenharmony_ci     information.
38061cb0ef41Sopenharmony_ci    """
38071cb0ef41Sopenharmony_ci    print("**** Not Implemented")
38081cb0ef41Sopenharmony_ci
38091cb0ef41Sopenharmony_ci  def do_u(self, args):
38101cb0ef41Sopenharmony_ci    """ see disassemble """
38111cb0ef41Sopenharmony_ci    return self.do_disassemble(args)
38121cb0ef41Sopenharmony_ci
38131cb0ef41Sopenharmony_ci  def do_disassemble(self, args):
38141cb0ef41Sopenharmony_ci    """
38151cb0ef41Sopenharmony_ci     Unassemble memory in the region [address, address + size).
38161cb0ef41Sopenharmony_ci
38171cb0ef41Sopenharmony_ci     If the size is not specified, a default value of 32 bytes is used.
38181cb0ef41Sopenharmony_ci     Synopsis: u 0x<address> 0x<size>
38191cb0ef41Sopenharmony_ci    """
38201cb0ef41Sopenharmony_ci    if len(args) != 0:
38211cb0ef41Sopenharmony_ci      args = args.split(' ')
38221cb0ef41Sopenharmony_ci      self.u_start = self.ParseAddressExpr(args[0])
38231cb0ef41Sopenharmony_ci      self.u_size = self.ParseAddressExpr(args[1]) if len(args) > 1 else 0x20
38241cb0ef41Sopenharmony_ci      skip = False
38251cb0ef41Sopenharmony_ci    else:
38261cb0ef41Sopenharmony_ci      # Skip the first instruction if we reuse the last address.
38271cb0ef41Sopenharmony_ci      skip = True
38281cb0ef41Sopenharmony_ci
38291cb0ef41Sopenharmony_ci    if not self.reader.IsValidAddress(self.u_start):
38301cb0ef41Sopenharmony_ci      print("Address %s is not contained within the minidump!" % (
38311cb0ef41Sopenharmony_ci          self.reader.FormatIntPtr(self.u_start)))
38321cb0ef41Sopenharmony_ci      return
38331cb0ef41Sopenharmony_ci    lines = self.reader.GetDisasmLines(self.u_start, self.u_size)
38341cb0ef41Sopenharmony_ci    if len(lines) == 0:
38351cb0ef41Sopenharmony_ci      print("Address %s could not be disassembled!" % (
38361cb0ef41Sopenharmony_ci          self.reader.FormatIntPtr(self.u_start)))
38371cb0ef41Sopenharmony_ci      print("    Could not disassemble using %s." % OBJDUMP_BIN)
38381cb0ef41Sopenharmony_ci      print("    Pass path to architecture specific objdump via --objdump?")
38391cb0ef41Sopenharmony_ci      return
38401cb0ef41Sopenharmony_ci    for line in lines:
38411cb0ef41Sopenharmony_ci      if skip:
38421cb0ef41Sopenharmony_ci        skip = False
38431cb0ef41Sopenharmony_ci        continue
38441cb0ef41Sopenharmony_ci      print(FormatDisasmLine(self.u_start, self.heap, line))
38451cb0ef41Sopenharmony_ci    # Set the next start address = last line
38461cb0ef41Sopenharmony_ci    self.u_start += lines[-1][0]
38471cb0ef41Sopenharmony_ci    print()
38481cb0ef41Sopenharmony_ci
38491cb0ef41Sopenharmony_ci  def do_EOF(self, none):
38501cb0ef41Sopenharmony_ci    raise KeyboardInterrupt
38511cb0ef41Sopenharmony_ci
38521cb0ef41Sopenharmony_ciEIP_PROXIMITY = 64
38531cb0ef41Sopenharmony_ci
38541cb0ef41Sopenharmony_ciCONTEXT_FOR_ARCH = {
38551cb0ef41Sopenharmony_ci    MD_CPU_ARCHITECTURE_AMD64:
38561cb0ef41Sopenharmony_ci      ['rax', 'rbx', 'rcx', 'rdx', 'rdi', 'rsi', 'rbp', 'rsp', 'rip',
38571cb0ef41Sopenharmony_ci       'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15'],
38581cb0ef41Sopenharmony_ci    MD_CPU_ARCHITECTURE_ARM:
38591cb0ef41Sopenharmony_ci      ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9',
38601cb0ef41Sopenharmony_ci       'r10', 'r11', 'r12', 'sp', 'lr', 'pc'],
38611cb0ef41Sopenharmony_ci    MD_CPU_ARCHITECTURE_ARM64:
38621cb0ef41Sopenharmony_ci      ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9',
38631cb0ef41Sopenharmony_ci       'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'r16', 'r17', 'r18', 'r19',
38641cb0ef41Sopenharmony_ci       'r20', 'r21', 'r22', 'r23', 'r24', 'r25', 'r26', 'r27', 'r28',
38651cb0ef41Sopenharmony_ci       'fp', 'lr', 'sp', 'pc'],
38661cb0ef41Sopenharmony_ci    MD_CPU_ARCHITECTURE_X86:
38671cb0ef41Sopenharmony_ci      ['eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', 'eip']
38681cb0ef41Sopenharmony_ci}
38691cb0ef41Sopenharmony_ci
38701cb0ef41Sopenharmony_ciKNOWN_MODULES = {'chrome.exe', 'chrome.dll'}
38711cb0ef41Sopenharmony_ci
38721cb0ef41Sopenharmony_cidef GetVersionString(ms, ls):
38731cb0ef41Sopenharmony_ci  return "%d.%d.%d.%d" % (ms >> 16, ms & 0xffff, ls >> 16, ls & 0xffff)
38741cb0ef41Sopenharmony_ci
38751cb0ef41Sopenharmony_ci
38761cb0ef41Sopenharmony_cidef GetModuleName(reader, module):
38771cb0ef41Sopenharmony_ci  name = reader.ReadMinidumpString(module.module_name_rva)
38781cb0ef41Sopenharmony_ci  # simplify for path manipulation
38791cb0ef41Sopenharmony_ci  name = name.encode('utf-8')
38801cb0ef41Sopenharmony_ci  return str(os.path.basename(str(name).replace("\\", "/")))
38811cb0ef41Sopenharmony_ci
38821cb0ef41Sopenharmony_ci
38831cb0ef41Sopenharmony_cidef PrintModuleDetails(reader, module):
38841cb0ef41Sopenharmony_ci  print("%s" % GetModuleName(reader, module))
38851cb0ef41Sopenharmony_ci  file_version = GetVersionString(module.version_info.dwFileVersionMS,
38861cb0ef41Sopenharmony_ci                                  module.version_info.dwFileVersionLS);
38871cb0ef41Sopenharmony_ci  product_version = GetVersionString(module.version_info.dwProductVersionMS,
38881cb0ef41Sopenharmony_ci                                     module.version_info.dwProductVersionLS)
38891cb0ef41Sopenharmony_ci  print("  base: %s" % reader.FormatIntPtr(module.base_of_image))
38901cb0ef41Sopenharmony_ci  print("  end: %s" % reader.FormatIntPtr(module.base_of_image +
38911cb0ef41Sopenharmony_ci                                          module.size_of_image))
38921cb0ef41Sopenharmony_ci  print("  file version: %s" % file_version)
38931cb0ef41Sopenharmony_ci  print("  product version: %s" % product_version)
38941cb0ef41Sopenharmony_ci  time_date_stamp = datetime.datetime.fromtimestamp(module.time_date_stamp)
38951cb0ef41Sopenharmony_ci  print("  timestamp: %s" % time_date_stamp)
38961cb0ef41Sopenharmony_ci
38971cb0ef41Sopenharmony_ci
38981cb0ef41Sopenharmony_cidef AnalyzeMinidump(options, minidump_name):
38991cb0ef41Sopenharmony_ci  reader = MinidumpReader(options, minidump_name)
39001cb0ef41Sopenharmony_ci  # Use a separate function to prevent leaking the minidump buffer through
39011cb0ef41Sopenharmony_ci  # ctypes in local variables.
39021cb0ef41Sopenharmony_ci  _AnalyzeMinidump(options, reader)
39031cb0ef41Sopenharmony_ci  reader.Dispose()
39041cb0ef41Sopenharmony_ci
39051cb0ef41Sopenharmony_ci
39061cb0ef41Sopenharmony_cidef _AnalyzeMinidump(options, reader):
39071cb0ef41Sopenharmony_ci  heap = None
39081cb0ef41Sopenharmony_ci
39091cb0ef41Sopenharmony_ci  stack_top = reader.ExceptionSP()
39101cb0ef41Sopenharmony_ci  stack_bottom = reader.StackBottom()
39111cb0ef41Sopenharmony_ci  stack_map = {reader.ExceptionIP(): -1}
39121cb0ef41Sopenharmony_ci  for slot in range(stack_top, stack_bottom, reader.MachinePointerSize()):
39131cb0ef41Sopenharmony_ci    maybe_address = reader.ReadUIntPtr(slot)
39141cb0ef41Sopenharmony_ci    if not maybe_address in stack_map:
39151cb0ef41Sopenharmony_ci      stack_map[maybe_address] = slot
39161cb0ef41Sopenharmony_ci
39171cb0ef41Sopenharmony_ci  heap = V8Heap(reader, stack_map)
39181cb0ef41Sopenharmony_ci  padawan = InspectionPadawan(reader, heap)
39191cb0ef41Sopenharmony_ci
39201cb0ef41Sopenharmony_ci  DebugPrint("========================================")
39211cb0ef41Sopenharmony_ci  if reader.exception is None:
39221cb0ef41Sopenharmony_ci    print("Minidump has no exception info")
39231cb0ef41Sopenharmony_ci  else:
39241cb0ef41Sopenharmony_ci    print("Address markers:")
39251cb0ef41Sopenharmony_ci    print("  T = valid tagged pointer in the minidump")
39261cb0ef41Sopenharmony_ci    print("  S = address on the exception stack")
39271cb0ef41Sopenharmony_ci    print("  C = address in loaded C/C++ module")
39281cb0ef41Sopenharmony_ci    print("  * = address in the minidump")
39291cb0ef41Sopenharmony_ci    print("")
39301cb0ef41Sopenharmony_ci    print("Exception info:")
39311cb0ef41Sopenharmony_ci    exception_thread = reader.ExceptionThread()
39321cb0ef41Sopenharmony_ci    print("  thread id: %d" % exception_thread.id)
39331cb0ef41Sopenharmony_ci    print("  code:      %08X" % reader.exception.exception.code)
39341cb0ef41Sopenharmony_ci    print("  context:")
39351cb0ef41Sopenharmony_ci    context = CONTEXT_FOR_ARCH[reader.arch]
39361cb0ef41Sopenharmony_ci    maxWidth = max(map(lambda s: len(s), context))
39371cb0ef41Sopenharmony_ci    for r in context:
39381cb0ef41Sopenharmony_ci      register_value = reader.Register(r)
39391cb0ef41Sopenharmony_ci      print("    %s: %s" % (r.rjust(maxWidth),
39401cb0ef41Sopenharmony_ci                            heap.FormatIntPtr(register_value)))
39411cb0ef41Sopenharmony_ci    # TODO(vitalyr): decode eflags.
39421cb0ef41Sopenharmony_ci    if reader.arch in [MD_CPU_ARCHITECTURE_ARM, MD_CPU_ARCHITECTURE_ARM64]:
39431cb0ef41Sopenharmony_ci      print("    cpsr: %s" % bin(reader.exception_context.cpsr)[2:])
39441cb0ef41Sopenharmony_ci    else:
39451cb0ef41Sopenharmony_ci      print("    eflags: %s" % bin(reader.exception_context.eflags)[2:])
39461cb0ef41Sopenharmony_ci
39471cb0ef41Sopenharmony_ci    print()
39481cb0ef41Sopenharmony_ci    print("  modules:")
39491cb0ef41Sopenharmony_ci    for module in reader.module_list.modules:
39501cb0ef41Sopenharmony_ci      name = GetModuleName(reader, module)
39511cb0ef41Sopenharmony_ci      if name in KNOWN_MODULES:
39521cb0ef41Sopenharmony_ci        print("    %s at %08X" % (name, module.base_of_image))
39531cb0ef41Sopenharmony_ci        reader.TryLoadSymbolsFor(name, module)
39541cb0ef41Sopenharmony_ci    print()
39551cb0ef41Sopenharmony_ci
39561cb0ef41Sopenharmony_ci    print("  stack-top:    %s" % heap.FormatIntPtr(reader.StackTop()))
39571cb0ef41Sopenharmony_ci    print("  stack-bottom: %s" % heap.FormatIntPtr(reader.StackBottom()))
39581cb0ef41Sopenharmony_ci    print("")
39591cb0ef41Sopenharmony_ci
39601cb0ef41Sopenharmony_ci    if options.shell:
39611cb0ef41Sopenharmony_ci      padawan.PrintStackTraceMessage(print_message=False)
39621cb0ef41Sopenharmony_ci
39631cb0ef41Sopenharmony_ci    print("Disassembly around exception.eip:")
39641cb0ef41Sopenharmony_ci    eip_symbol = reader.FindSymbol(reader.ExceptionIP())
39651cb0ef41Sopenharmony_ci    if eip_symbol is not None:
39661cb0ef41Sopenharmony_ci      print(eip_symbol)
39671cb0ef41Sopenharmony_ci    disasm_start = reader.ExceptionIP() - EIP_PROXIMITY
39681cb0ef41Sopenharmony_ci    disasm_bytes = 2 * EIP_PROXIMITY
39691cb0ef41Sopenharmony_ci    if (options.full):
39701cb0ef41Sopenharmony_ci      full_range = reader.FindRegion(reader.ExceptionIP())
39711cb0ef41Sopenharmony_ci      if full_range is not None:
39721cb0ef41Sopenharmony_ci        disasm_start = full_range[0]
39731cb0ef41Sopenharmony_ci        disasm_bytes = full_range[1]
39741cb0ef41Sopenharmony_ci
39751cb0ef41Sopenharmony_ci    lines = reader.GetDisasmLines(disasm_start, disasm_bytes)
39761cb0ef41Sopenharmony_ci
39771cb0ef41Sopenharmony_ci    if not lines:
39781cb0ef41Sopenharmony_ci      print("Could not disassemble using %s." % OBJDUMP_BIN)
39791cb0ef41Sopenharmony_ci      print("Pass path to architecture specific objdump via --objdump?")
39801cb0ef41Sopenharmony_ci
39811cb0ef41Sopenharmony_ci    for line in lines:
39821cb0ef41Sopenharmony_ci      print(FormatDisasmLine(disasm_start, heap, line))
39831cb0ef41Sopenharmony_ci    print()
39841cb0ef41Sopenharmony_ci
39851cb0ef41Sopenharmony_ci  if heap is None:
39861cb0ef41Sopenharmony_ci    heap = V8Heap(reader, None)
39871cb0ef41Sopenharmony_ci
39881cb0ef41Sopenharmony_ci  if options.full:
39891cb0ef41Sopenharmony_ci    FullDump(reader, heap)
39901cb0ef41Sopenharmony_ci
39911cb0ef41Sopenharmony_ci  if options.command:
39921cb0ef41Sopenharmony_ci    InspectionShell(reader, heap).onecmd(options.command)
39931cb0ef41Sopenharmony_ci
39941cb0ef41Sopenharmony_ci  if options.shell:
39951cb0ef41Sopenharmony_ci    try:
39961cb0ef41Sopenharmony_ci      InspectionShell(reader, heap).cmdloop("type help to get help")
39971cb0ef41Sopenharmony_ci    except KeyboardInterrupt:
39981cb0ef41Sopenharmony_ci      print("Kthxbye.")
39991cb0ef41Sopenharmony_ci  elif not options.command:
40001cb0ef41Sopenharmony_ci    if reader.exception is not None:
40011cb0ef41Sopenharmony_ci      print("Annotated stack (from exception.esp to bottom):")
40021cb0ef41Sopenharmony_ci      stack_start = padawan.PrintStackTraceMessage()
40031cb0ef41Sopenharmony_ci      padawan.InterpretMemory(stack_start, stack_bottom)
40041cb0ef41Sopenharmony_ci
40051cb0ef41Sopenharmony_ci
40061cb0ef41Sopenharmony_ciif __name__ == "__main__":
40071cb0ef41Sopenharmony_ci  parser = optparse.OptionParser(USAGE)
40081cb0ef41Sopenharmony_ci  parser.add_option("-s", "--shell", dest="shell", action="store_true",
40091cb0ef41Sopenharmony_ci                    help="start an interactive inspector shell")
40101cb0ef41Sopenharmony_ci  parser.add_option("-w", "--web", dest="web", action="store_true",
40111cb0ef41Sopenharmony_ci                    help="start a web server on localhost:%i" % PORT_NUMBER)
40121cb0ef41Sopenharmony_ci  parser.add_option("-c", "--command", dest="command", default="",
40131cb0ef41Sopenharmony_ci                    help="run an interactive inspector shell command and exit")
40141cb0ef41Sopenharmony_ci  parser.add_option("-f", "--full", dest="full", action="store_true",
40151cb0ef41Sopenharmony_ci                    help="dump all information contained in the minidump")
40161cb0ef41Sopenharmony_ci  parser.add_option("--symdir", dest="symdir", default=".",
40171cb0ef41Sopenharmony_ci                    help="directory containing *.pdb.sym file with symbols")
40181cb0ef41Sopenharmony_ci  parser.add_option("--objdump", default="",
40191cb0ef41Sopenharmony_ci                    help="objdump tool to use [default: %s]" % (
40201cb0ef41Sopenharmony_ci                        DEFAULT_OBJDUMP_BIN))
40211cb0ef41Sopenharmony_ci  options, args = parser.parse_args()
40221cb0ef41Sopenharmony_ci  if len(args) != 1:
40231cb0ef41Sopenharmony_ci    parser.print_help()
40241cb0ef41Sopenharmony_ci    sys.exit(1)
40251cb0ef41Sopenharmony_ci  if options.web:
40261cb0ef41Sopenharmony_ci    try:
40271cb0ef41Sopenharmony_ci      server = InspectionWebServer(PORT_NUMBER, options, args[0])
40281cb0ef41Sopenharmony_ci      print('Started httpserver on port ' , PORT_NUMBER)
40291cb0ef41Sopenharmony_ci      webbrowser.open('http://localhost:%i/summary.html' % PORT_NUMBER)
40301cb0ef41Sopenharmony_ci      server.serve_forever()
40311cb0ef41Sopenharmony_ci    except KeyboardInterrupt:
40321cb0ef41Sopenharmony_ci      print('^C received, shutting down the web server')
40331cb0ef41Sopenharmony_ci      server.socket.close()
40341cb0ef41Sopenharmony_ci  else:
40351cb0ef41Sopenharmony_ci    AnalyzeMinidump(options, args[0])
4036