# Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# This file contains a set of utilities for parsing minidumps.

import ctypes
import mmap
import os
import sys


class Enum(object):
  def __init__(self, type, name2value):
    self.name2value = name2value
    self.value2name = {v: k for k, v in name2value.iteritems()}
    self.type = type

  def from_raw(self, v):
    if v not in self.value2name:
      return 'Unknown(' + str(v) + ')'
    return self.value2name[v]

  def to_raw(self, v):
    return self.name2value[v]


class Descriptor(object):
  """A handy wrapper over ctypes.Structure"""

  def __init__(self, fields):
    self.fields = fields
    self.ctype = Descriptor._GetCtype(fields)
    self.size = ctypes.sizeof(self.ctype)

  def Read(self, address):
    return self.ctype.from_address(address)

  @staticmethod
  def _GetCtype(fields):
    raw_fields = []
    wrappers = {}
    for field in fields:
      (name, type) = field
      if isinstance(type, Enum):
        raw_fields.append(('_raw_' + name, type.type))
        wrappers[name] = type
      else:
        raw_fields.append(field)

    class Raw(ctypes.Structure):
      _fields_ = raw_fields
      _pack_ = 1

      def __getattribute__(self, name):
        if name in wrappers:
          return wrappers[name].from_raw(getattr(self, '_raw_' + name))
        else:
          return ctypes.Structure.__getattribute__(self, name)

      def __repr__(self):
        return '{' + ', '.join('%s: %s' % (field, self.__getattribute__(field))
                               for field, _ in fields) + '}'

    return Raw


# Structures below are based on the information in the MSDN pages and
# Breakpad/Crashpad sources.


MINIDUMP_HEADER = Descriptor([
  ('signature', ctypes.c_uint32),
  ('version', ctypes.c_uint32),
  ('stream_count', ctypes.c_uint32),
  ('stream_directories_rva', ctypes.c_uint32),
  ('checksum', ctypes.c_uint32),
  ('time_date_stampt', ctypes.c_uint32),
  ('flags', ctypes.c_uint64)
])


MINIDUMP_LOCATION_DESCRIPTOR = Descriptor([
  ('data_size', ctypes.c_uint32),
  ('rva', ctypes.c_uint32)
])


MINIDUMP_STREAM_TYPE = {
  'MD_UNUSED_STREAM': 0,
  'MD_RESERVED_STREAM_0': 1,
  'MD_RESERVED_STREAM_1': 2,
  'MD_THREAD_LIST_STREAM': 3,
  'MD_MODULE_LIST_STREAM': 4,
  'MD_MEMORY_LIST_STREAM': 5,
  'MD_EXCEPTION_STREAM': 6,
  'MD_SYSTEM_INFO_STREAM': 7,
  'MD_THREAD_EX_LIST_STREAM': 8,
  'MD_MEMORY_64_LIST_STREAM': 9,
  'MD_COMMENT_STREAM_A': 10,
  'MD_COMMENT_STREAM_W': 11,
  'MD_HANDLE_DATA_STREAM': 12,
  'MD_FUNCTION_TABLE_STREAM': 13,
  'MD_UNLOADED_MODULE_LIST_STREAM': 14,
  'MD_MISC_INFO_STREAM': 15,
  'MD_MEMORY_INFO_LIST_STREAM': 16,
  'MD_THREAD_INFO_LIST_STREAM': 17,
  'MD_HANDLE_OPERATION_LIST_STREAM': 18,
}


MINIDUMP_DIRECTORY = Descriptor([
  ('stream_type', Enum(ctypes.c_uint32, MINIDUMP_STREAM_TYPE)),
  ('location', MINIDUMP_LOCATION_DESCRIPTOR.ctype)
])


MINIDUMP_MISC_INFO_2 = Descriptor([
  ('SizeOfInfo', ctypes.c_uint32),
  ('Flags1', ctypes.c_uint32),
  ('ProcessId', ctypes.c_uint32),
  ('ProcessCreateTime', ctypes.c_uint32),
  ('ProcessUserTime', ctypes.c_uint32),
  ('ProcessKernelTime', ctypes.c_uint32),
  ('ProcessorMaxMhz', ctypes.c_uint32),
  ('ProcessorCurrentMhz', ctypes.c_uint32),
  ('ProcessorMhzLimit', ctypes.c_uint32),
  ('ProcessorMaxIdleState', ctypes.c_uint32),
  ('ProcessorCurrentIdleState', ctypes.c_uint32),
]);


MINIDUMP_MISC1_PROCESS_ID = 0x00000001


# A helper to get a raw address of the memory mapped buffer returned by
# mmap.
def BufferToAddress(buf):
  obj = ctypes.py_object(buf)
  address = ctypes.c_void_p()
  length = ctypes.c_ssize_t()
  ctypes.pythonapi.PyObject_AsReadBuffer(
      obj, ctypes.byref(address), ctypes.byref(length))
  return address.value


class MinidumpFile(object):
  """Class for reading minidump files."""
  _HEADER_MAGIC = 0x504d444d

  def __init__(self, minidump_name):
    self.minidump_name = minidump_name
    self.minidump_file = open(minidump_name, 'r')
    self.minidump = mmap.mmap(self.minidump_file.fileno(), 0, access=mmap.ACCESS_READ)
    self.minidump_address = BufferToAddress(self.minidump)
    self.header = self.Read(MINIDUMP_HEADER, 0)
    if self.header.signature != MinidumpFile._HEADER_MAGIC:
      raise Exception('Unsupported minidump header magic')
    self.directories = []
    offset = self.header.stream_directories_rva
    for _ in xrange(self.header.stream_count):
      self.directories.append(self.Read(MINIDUMP_DIRECTORY, offset))
      offset += MINIDUMP_DIRECTORY.size

  def GetProcessId(self):
    for dir in self.directories:
      if dir.stream_type == 'MD_MISC_INFO_STREAM':
        info = self.Read(MINIDUMP_MISC_INFO_2, dir.location.rva)
        if info.Flags1 & MINIDUMP_MISC1_PROCESS_ID != 0:
          return info.ProcessId
    return -1

  def Read(self, what, offset):
    return what.Read(self.minidump_address + offset)

  def __enter__(self):
    return self

  def __exit__(self, type, value, traceback):
    self.minidump.close()
    self.minidump_file.close()


# Returns process id of the crashed process recorded in the given minidump.
def GetProcessIdFromDump(path):
  try:
    with MinidumpFile(path) as f:
      return int(f.GetProcessId())
  except:
    return -1
