Windows MiniDump: PHP parsing library

Windows MiniDump (MDMP) file provides a concise way to store process core dumps, which is useful for debugging. Given its small size, modularity, some cross-platform features and native support in some debuggers, it is particularly useful for crash reporting, and is used for that purpose in Windows and Google Chrome projects.

The file itself is a container, which contains a number of typed "streams", which contain some data according to its type attribute.

KS implementation details

License: CC0-1.0

This page hosts a formal specification of Windows MiniDump using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

PHP source code to parse Windows MiniDump

WindowsMinidump.php

<?php
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

/**
 * Windows MiniDump (MDMP) file provides a concise way to store process
 * core dumps, which is useful for debugging. Given its small size,
 * modularity, some cross-platform features and native support in some
 * debuggers, it is particularly useful for crash reporting, and is
 * used for that purpose in Windows and Google Chrome projects.
 * 
 * The file itself is a container, which contains a number of typed
 * "streams", which contain some data according to its type attribute.
 */

namespace {
    class WindowsMinidump extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_magic1 = $this->_io->readBytes(4);
            if (!($this->magic1() == "\x4D\x44\x4D\x50")) {
                throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x4D\x44\x4D\x50", $this->magic1(), $this->_io(), "/seq/0");
            }
            $this->_m_magic2 = $this->_io->readBytes(2);
            if (!($this->magic2() == "\x93\xA7")) {
                throw new \Kaitai\Struct\Error\ValidationNotEqualError("\x93\xA7", $this->magic2(), $this->_io(), "/seq/1");
            }
            $this->_m_version = $this->_io->readU2le();
            $this->_m_numStreams = $this->_io->readU4le();
            $this->_m_ofsStreams = $this->_io->readU4le();
            $this->_m_checksum = $this->_io->readU4le();
            $this->_m_timestamp = $this->_io->readU4le();
            $this->_m_flags = $this->_io->readU8le();
        }
        protected $_m_streams;
        public function streams() {
            if ($this->_m_streams !== null)
                return $this->_m_streams;
            $_pos = $this->_io->pos();
            $this->_io->seek($this->ofsStreams());
            $this->_m_streams = [];
            $n = $this->numStreams();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_streams[] = new \WindowsMinidump\Dir($this->_io, $this, $this->_root);
            }
            $this->_io->seek($_pos);
            return $this->_m_streams;
        }
        protected $_m_magic1;
        protected $_m_magic2;
        protected $_m_version;
        protected $_m_numStreams;
        protected $_m_ofsStreams;
        protected $_m_checksum;
        protected $_m_timestamp;
        protected $_m_flags;
        public function magic1() { return $this->_m_magic1; }
        public function magic2() { return $this->_m_magic2; }
        public function version() { return $this->_m_version; }
        public function numStreams() { return $this->_m_numStreams; }
        public function ofsStreams() { return $this->_m_ofsStreams; }
        public function checksum() { return $this->_m_checksum; }
        public function timestamp() { return $this->_m_timestamp; }
        public function flags() { return $this->_m_flags; }
    }
}

namespace WindowsMinidump {
    class ThreadList extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\Dir $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_numThreads = $this->_io->readU4le();
            $this->_m_threads = [];
            $n = $this->numThreads();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_threads[] = new \WindowsMinidump\Thread($this->_io, $this, $this->_root);
            }
        }
        protected $_m_numThreads;
        protected $_m_threads;
        public function numThreads() { return $this->_m_numThreads; }
        public function threads() { return $this->_m_threads; }
    }
}

namespace WindowsMinidump {
    class LocationDescriptor extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_lenData = $this->_io->readU4le();
            $this->_m_ofsData = $this->_io->readU4le();
        }
        protected $_m_data;
        public function data() {
            if ($this->_m_data !== null)
                return $this->_m_data;
            $io = $this->_root()->_io();
            $_pos = $io->pos();
            $io->seek($this->ofsData());
            $this->_m_data = $io->readBytes($this->lenData());
            $io->seek($_pos);
            return $this->_m_data;
        }
        protected $_m_lenData;
        protected $_m_ofsData;
        public function lenData() { return $this->_m_lenData; }
        public function ofsData() { return $this->_m_ofsData; }
    }
}

/**
 * Specific string serialization scheme used in MiniDump format is
 * actually a simple 32-bit length-prefixed UTF-16 string.
 */

namespace WindowsMinidump {
    class MinidumpString extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\SystemInfo $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_lenStr = $this->_io->readU4le();
            $this->_m_str = \Kaitai\Struct\Stream::bytesToStr($this->_io->readBytes($this->lenStr()), "UTF-16LE");
        }
        protected $_m_lenStr;
        protected $_m_str;
        public function lenStr() { return $this->_m_lenStr; }
        public function str() { return $this->_m_str; }
    }
}

/**
 * "System info" stream provides basic information about the
 * hardware and operating system which produces this dump.
 */

namespace WindowsMinidump {
    class SystemInfo extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\Dir $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_cpuArch = $this->_io->readU2le();
            $this->_m_cpuLevel = $this->_io->readU2le();
            $this->_m_cpuRevision = $this->_io->readU2le();
            $this->_m_numCpus = $this->_io->readU1();
            $this->_m_osType = $this->_io->readU1();
            $this->_m_osVerMajor = $this->_io->readU4le();
            $this->_m_osVerMinor = $this->_io->readU4le();
            $this->_m_osBuild = $this->_io->readU4le();
            $this->_m_osPlatform = $this->_io->readU4le();
            $this->_m_ofsServicePack = $this->_io->readU4le();
            $this->_m_osSuiteMask = $this->_io->readU2le();
            $this->_m_reserved2 = $this->_io->readU2le();
        }
        protected $_m_servicePack;
        public function servicePack() {
            if ($this->_m_servicePack !== null)
                return $this->_m_servicePack;
            if ($this->ofsServicePack() > 0) {
                $io = $this->_root()->_io();
                $_pos = $io->pos();
                $io->seek($this->ofsServicePack());
                $this->_m_servicePack = new \WindowsMinidump\MinidumpString($io, $this, $this->_root);
                $io->seek($_pos);
            }
            return $this->_m_servicePack;
        }
        protected $_m_cpuArch;
        protected $_m_cpuLevel;
        protected $_m_cpuRevision;
        protected $_m_numCpus;
        protected $_m_osType;
        protected $_m_osVerMajor;
        protected $_m_osVerMinor;
        protected $_m_osBuild;
        protected $_m_osPlatform;
        protected $_m_ofsServicePack;
        protected $_m_osSuiteMask;
        protected $_m_reserved2;
        public function cpuArch() { return $this->_m_cpuArch; }
        public function cpuLevel() { return $this->_m_cpuLevel; }
        public function cpuRevision() { return $this->_m_cpuRevision; }
        public function numCpus() { return $this->_m_numCpus; }
        public function osType() { return $this->_m_osType; }
        public function osVerMajor() { return $this->_m_osVerMajor; }
        public function osVerMinor() { return $this->_m_osVerMinor; }
        public function osBuild() { return $this->_m_osBuild; }
        public function osPlatform() { return $this->_m_osPlatform; }
        public function ofsServicePack() { return $this->_m_ofsServicePack; }
        public function osSuiteMask() { return $this->_m_osSuiteMask; }
        public function reserved2() { return $this->_m_reserved2; }
    }
}

namespace WindowsMinidump\SystemInfo {
    class CpuArchs {
        const INTEL = 0;
        const ARM = 5;
        const IA64 = 6;
        const AMD64 = 9;
        const UNKNOWN = 65535;
    }
}

namespace WindowsMinidump {
    class ExceptionRecord extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\ExceptionStream $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_code = $this->_io->readU4le();
            $this->_m_flags = $this->_io->readU4le();
            $this->_m_innerException = $this->_io->readU8le();
            $this->_m_addr = $this->_io->readU8le();
            $this->_m_numParams = $this->_io->readU4le();
            $this->_m_reserved = $this->_io->readU4le();
            $this->_m_params = [];
            $n = 15;
            for ($i = 0; $i < $n; $i++) {
                $this->_m_params[] = $this->_io->readU8le();
            }
        }
        protected $_m_code;
        protected $_m_flags;
        protected $_m_innerException;
        protected $_m_addr;
        protected $_m_numParams;
        protected $_m_reserved;
        protected $_m_params;
        public function code() { return $this->_m_code; }
        public function flags() { return $this->_m_flags; }
        public function innerException() { return $this->_m_innerException; }

        /**
         * Memory address where exception has occurred
         */
        public function addr() { return $this->_m_addr; }
        public function numParams() { return $this->_m_numParams; }
        public function reserved() { return $this->_m_reserved; }

        /**
         * Additional parameters passed along with exception raise
         * function (for WinAPI, that is `RaiseException`). Meaning is
         * exception-specific. Given that this type is originally
         * defined by a C structure, it is described there as array of
         * fixed number of elements (`EXCEPTION_MAXIMUM_PARAMETERS` =
         * 15), but in reality only first `num_params` would be used.
         */
        public function params() { return $this->_m_params; }
    }
}

namespace WindowsMinidump {
    class MiscInfo extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\Dir $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_lenInfo = $this->_io->readU4le();
            $this->_m_flags1 = $this->_io->readU4le();
            $this->_m_processId = $this->_io->readU4le();
            $this->_m_processCreateTime = $this->_io->readU4le();
            $this->_m_processUserTime = $this->_io->readU4le();
            $this->_m_processKernelTime = $this->_io->readU4le();
            $this->_m_cpuMaxMhz = $this->_io->readU4le();
            $this->_m_cpuCurMhz = $this->_io->readU4le();
            $this->_m_cpuLimitMhz = $this->_io->readU4le();
            $this->_m_cpuMaxIdleState = $this->_io->readU4le();
            $this->_m_cpuCurIdleState = $this->_io->readU4le();
        }
        protected $_m_lenInfo;
        protected $_m_flags1;
        protected $_m_processId;
        protected $_m_processCreateTime;
        protected $_m_processUserTime;
        protected $_m_processKernelTime;
        protected $_m_cpuMaxMhz;
        protected $_m_cpuCurMhz;
        protected $_m_cpuLimitMhz;
        protected $_m_cpuMaxIdleState;
        protected $_m_cpuCurIdleState;
        public function lenInfo() { return $this->_m_lenInfo; }
        public function flags1() { return $this->_m_flags1; }
        public function processId() { return $this->_m_processId; }
        public function processCreateTime() { return $this->_m_processCreateTime; }
        public function processUserTime() { return $this->_m_processUserTime; }
        public function processKernelTime() { return $this->_m_processKernelTime; }
        public function cpuMaxMhz() { return $this->_m_cpuMaxMhz; }
        public function cpuCurMhz() { return $this->_m_cpuCurMhz; }
        public function cpuLimitMhz() { return $this->_m_cpuLimitMhz; }
        public function cpuMaxIdleState() { return $this->_m_cpuMaxIdleState; }
        public function cpuCurIdleState() { return $this->_m_cpuCurIdleState; }
    }
}

namespace WindowsMinidump {
    class Dir extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_streamType = $this->_io->readU4le();
            $this->_m_lenData = $this->_io->readU4le();
            $this->_m_ofsData = $this->_io->readU4le();
        }
        protected $_m_data;
        public function data() {
            if ($this->_m_data !== null)
                return $this->_m_data;
            $_pos = $this->_io->pos();
            $this->_io->seek($this->ofsData());
            switch ($this->streamType()) {
                case \WindowsMinidump\StreamTypes::MEMORY_LIST:
                    $this->_m__raw_data = $this->_io->readBytes($this->lenData());
                    $_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
                    $this->_m_data = new \WindowsMinidump\MemoryList($_io__raw_data, $this, $this->_root);
                    break;
                case \WindowsMinidump\StreamTypes::MISC_INFO:
                    $this->_m__raw_data = $this->_io->readBytes($this->lenData());
                    $_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
                    $this->_m_data = new \WindowsMinidump\MiscInfo($_io__raw_data, $this, $this->_root);
                    break;
                case \WindowsMinidump\StreamTypes::THREAD_LIST:
                    $this->_m__raw_data = $this->_io->readBytes($this->lenData());
                    $_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
                    $this->_m_data = new \WindowsMinidump\ThreadList($_io__raw_data, $this, $this->_root);
                    break;
                case \WindowsMinidump\StreamTypes::EXCEPTION:
                    $this->_m__raw_data = $this->_io->readBytes($this->lenData());
                    $_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
                    $this->_m_data = new \WindowsMinidump\ExceptionStream($_io__raw_data, $this, $this->_root);
                    break;
                case \WindowsMinidump\StreamTypes::SYSTEM_INFO:
                    $this->_m__raw_data = $this->_io->readBytes($this->lenData());
                    $_io__raw_data = new \Kaitai\Struct\Stream($this->_m__raw_data);
                    $this->_m_data = new \WindowsMinidump\SystemInfo($_io__raw_data, $this, $this->_root);
                    break;
                default:
                    $this->_m_data = $this->_io->readBytes($this->lenData());
                    break;
            }
            $this->_io->seek($_pos);
            return $this->_m_data;
        }
        protected $_m_streamType;
        protected $_m_lenData;
        protected $_m_ofsData;
        protected $_m__raw_data;
        public function streamType() { return $this->_m_streamType; }
        public function lenData() { return $this->_m_lenData; }
        public function ofsData() { return $this->_m_ofsData; }
        public function _raw_data() { return $this->_m__raw_data; }
    }
}

namespace WindowsMinidump {
    class Thread extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\ThreadList $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_threadId = $this->_io->readU4le();
            $this->_m_suspendCount = $this->_io->readU4le();
            $this->_m_priorityClass = $this->_io->readU4le();
            $this->_m_priority = $this->_io->readU4le();
            $this->_m_teb = $this->_io->readU8le();
            $this->_m_stack = new \WindowsMinidump\MemoryDescriptor($this->_io, $this, $this->_root);
            $this->_m_threadContext = new \WindowsMinidump\LocationDescriptor($this->_io, $this, $this->_root);
        }
        protected $_m_threadId;
        protected $_m_suspendCount;
        protected $_m_priorityClass;
        protected $_m_priority;
        protected $_m_teb;
        protected $_m_stack;
        protected $_m_threadContext;
        public function threadId() { return $this->_m_threadId; }
        public function suspendCount() { return $this->_m_suspendCount; }
        public function priorityClass() { return $this->_m_priorityClass; }
        public function priority() { return $this->_m_priority; }

        /**
         * Thread Environment Block
         */
        public function teb() { return $this->_m_teb; }
        public function stack() { return $this->_m_stack; }
        public function threadContext() { return $this->_m_threadContext; }
    }
}

namespace WindowsMinidump {
    class MemoryList extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\Dir $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_numMemRanges = $this->_io->readU4le();
            $this->_m_memRanges = [];
            $n = $this->numMemRanges();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_memRanges[] = new \WindowsMinidump\MemoryDescriptor($this->_io, $this, $this->_root);
            }
        }
        protected $_m_numMemRanges;
        protected $_m_memRanges;
        public function numMemRanges() { return $this->_m_numMemRanges; }
        public function memRanges() { return $this->_m_memRanges; }
    }
}

namespace WindowsMinidump {
    class MemoryDescriptor extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_addrMemoryRange = $this->_io->readU8le();
            $this->_m_memory = new \WindowsMinidump\LocationDescriptor($this->_io, $this, $this->_root);
        }
        protected $_m_addrMemoryRange;
        protected $_m_memory;
        public function addrMemoryRange() { return $this->_m_addrMemoryRange; }
        public function memory() { return $this->_m_memory; }
    }
}

namespace WindowsMinidump {
    class ExceptionStream extends \Kaitai\Struct\Struct {
        public function __construct(\Kaitai\Struct\Stream $_io, \WindowsMinidump\Dir $_parent = null, \WindowsMinidump $_root = null) {
            parent::__construct($_io, $_parent, $_root);
            $this->_read();
        }

        private function _read() {
            $this->_m_threadId = $this->_io->readU4le();
            $this->_m_reserved = $this->_io->readU4le();
            $this->_m_exceptionRec = new \WindowsMinidump\ExceptionRecord($this->_io, $this, $this->_root);
            $this->_m_threadContext = new \WindowsMinidump\LocationDescriptor($this->_io, $this, $this->_root);
        }
        protected $_m_threadId;
        protected $_m_reserved;
        protected $_m_exceptionRec;
        protected $_m_threadContext;
        public function threadId() { return $this->_m_threadId; }
        public function reserved() { return $this->_m_reserved; }
        public function exceptionRec() { return $this->_m_exceptionRec; }
        public function threadContext() { return $this->_m_threadContext; }
    }
}

namespace WindowsMinidump {
    class StreamTypes {
        const UNUSED = 0;
        const RESERVED_0 = 1;
        const RESERVED_1 = 2;
        const THREAD_LIST = 3;
        const MODULE_LIST = 4;
        const MEMORY_LIST = 5;
        const EXCEPTION = 6;
        const SYSTEM_INFO = 7;
        const THREAD_EX_LIST = 8;
        const MEMORY_64_LIST = 9;
        const COMMENT_A = 10;
        const COMMENT_W = 11;
        const HANDLE_DATA = 12;
        const FUNCTION_TABLE = 13;
        const UNLOADED_MODULE_LIST = 14;
        const MISC_INFO = 15;
        const MEMORY_INFO_LIST = 16;
        const THREAD_INFO_LIST = 17;
        const HANDLE_OPERATION_LIST = 18;
        const TOKEN = 19;
        const JAVA_SCRIPT_DATA = 20;
        const SYSTEM_MEMORY_INFO = 21;
        const PROCESS_VM_VOUNTERS = 22;
        const IPT_TRACE = 23;
        const THREAD_NAMES = 24;
        const CE_NULL = 32768;
        const CE_SYSTEM_INFO = 32769;
        const CE_EXCEPTION = 32770;
        const CE_MODULE_LIST = 32771;
        const CE_PROCESS_LIST = 32772;
        const CE_THREAD_LIST = 32773;
        const CE_THREAD_CONTEXT_LIST = 32774;
        const CE_THREAD_CALL_STACK_LIST = 32775;
        const CE_MEMORY_VIRTUAL_LIST = 32776;
        const CE_MEMORY_PHYSICAL_LIST = 32777;
        const CE_BUCKET_PARAMETERS = 32778;
        const CE_PROCESS_MODULE_MAP = 32779;
        const CE_DIAGNOSIS_LIST = 32780;
        const MD_CRASHPAD_INFO_STREAM = 1129316353;
        const MD_RAW_BREAKPAD_INFO = 1197932545;
        const MD_RAW_ASSERTION_INFO = 1197932546;
        const MD_LINUX_CPU_INFO = 1197932547;
        const MD_LINUX_PROC_STATUS = 1197932548;
        const MD_LINUX_LSB_RELEASE = 1197932549;
        const MD_LINUX_CMD_LINE = 1197932550;
        const MD_LINUX_ENVIRON = 1197932551;
        const MD_LINUX_AUXV = 1197932552;
        const MD_LINUX_MAPS = 1197932553;
        const MD_LINUX_DSO_DEBUG = 1197932554;
    }
}