Windows MiniDump: C++/STL 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.

Usage

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream).
    • One can open a stream for reading from a local file:
      #include <fstream>
      
      std::ifstream is("path/to/local/file.windows_minidump", std::ifstream::binary);
    • Or one can prepare a stream for reading from existing std::string str:
      #include <sstream>
      
      std::istringstream is(str);
    • Or one can parse arbitrary char* buffer in memory, given that we know its size:
      #include <sstream>
      
      const char buf[] = { ... };
      std::string str(buf, sizeof buf);
      std::istringstream is(str);
  2. We need to wrap our input stream into Kaitai stream:
    #include <kaitai/kaitaistream.h>
    
    kaitai::kstream ks(&is);
  3. And finally, we can invoke the parsing:
    windows_minidump_t data(&ks);

After that, one can get various attributes from the structure by invoking getter methods like:

data.magic1() // => get magic1

C++/STL source code to parse Windows MiniDump

windows_minidump.h

#ifndef WINDOWS_MINIDUMP_H_
#define WINDOWS_MINIDUMP_H_

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

#include "kaitai/kaitaistruct.h"

#include <stdint.h>
#include <vector>

#if KAITAI_STRUCT_VERSION < 7000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.7 or later is required"
#endif

/**
 * 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.
 * \sa Source
 */

class windows_minidump_t : public kaitai::kstruct {

public:
    class thread_list_t;
    class location_descriptor_t;
    class minidump_string_t;
    class system_info_t;
    class exception_record_t;
    class misc_info_t;
    class dir_t;
    class thread_t;
    class memory_list_t;
    class memory_descriptor_t;
    class exception_stream_t;

    enum stream_types_t {
        STREAM_TYPES_UNUSED = 0,
        STREAM_TYPES_RESERVED_0 = 1,
        STREAM_TYPES_RESERVED_1 = 2,
        STREAM_TYPES_THREAD_LIST = 3,
        STREAM_TYPES_MODULE_LIST = 4,
        STREAM_TYPES_MEMORY_LIST = 5,
        STREAM_TYPES_EXCEPTION = 6,
        STREAM_TYPES_SYSTEM_INFO = 7,
        STREAM_TYPES_THREAD_EX_LIST = 8,
        STREAM_TYPES_MEMORY_64_LIST = 9,
        STREAM_TYPES_COMMENT_A = 10,
        STREAM_TYPES_COMMENT_W = 11,
        STREAM_TYPES_HANDLE_DATA = 12,
        STREAM_TYPES_FUNCTION_TABLE = 13,
        STREAM_TYPES_UNLOADED_MODULE_LIST = 14,
        STREAM_TYPES_MISC_INFO = 15,
        STREAM_TYPES_MEMORY_INFO_LIST = 16,
        STREAM_TYPES_THREAD_INFO_LIST = 17,
        STREAM_TYPES_HANDLE_OPERATION_LIST = 18
    };

    windows_minidump_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, windows_minidump_t* p__root = 0);

private:
    void _read();

public:
    ~windows_minidump_t();

    /**
     * \sa Source
     */

    class thread_list_t : public kaitai::kstruct {

    public:

        thread_list_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~thread_list_t();

    private:
        uint32_t m_num_threads;
        std::vector<thread_t*>* m_threads;
        windows_minidump_t* m__root;
        windows_minidump_t::dir_t* m__parent;

    public:
        uint32_t num_threads() const { return m_num_threads; }
        std::vector<thread_t*>* threads() const { return m_threads; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::dir_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class location_descriptor_t : public kaitai::kstruct {

    public:

        location_descriptor_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~location_descriptor_t();

    private:
        bool f_data;
        std::string m_data;

    public:
        std::string data();

    private:
        uint32_t m_len_data;
        uint32_t m_ofs_data;
        windows_minidump_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        uint32_t len_data() const { return m_len_data; }
        uint32_t ofs_data() const { return m_ofs_data; }
        windows_minidump_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

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

    class minidump_string_t : public kaitai::kstruct {

    public:

        minidump_string_t(kaitai::kstream* p__io, windows_minidump_t::system_info_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~minidump_string_t();

    private:
        uint32_t m_len_str;
        std::string m_str;
        windows_minidump_t* m__root;
        windows_minidump_t::system_info_t* m__parent;

    public:
        uint32_t len_str() const { return m_len_str; }
        std::string str() const { return m_str; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::system_info_t* _parent() const { return m__parent; }
    };

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

    class system_info_t : public kaitai::kstruct {

    public:

        enum cpu_archs_t {
            CPU_ARCHS_INTEL = 0,
            CPU_ARCHS_ARM = 5,
            CPU_ARCHS_IA64 = 6,
            CPU_ARCHS_AMD64 = 9,
            CPU_ARCHS_UNKNOWN = 65535
        };

        system_info_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~system_info_t();

    private:
        bool f_service_pack;
        minidump_string_t* m_service_pack;
        bool n_service_pack;

    public:
        bool _is_null_service_pack() { service_pack(); return n_service_pack; };

    private:

    public:
        minidump_string_t* service_pack();

    private:
        cpu_archs_t m_cpu_arch;
        uint16_t m_cpu_level;
        uint16_t m_cpu_revision;
        uint8_t m_num_cpus;
        uint8_t m_os_type;
        uint32_t m_os_ver_major;
        uint32_t m_os_ver_minor;
        uint32_t m_os_build;
        uint32_t m_os_platform;
        uint32_t m_ofs_service_pack;
        uint16_t m_os_suite_mask;
        uint16_t m_reserved2;
        windows_minidump_t* m__root;
        windows_minidump_t::dir_t* m__parent;

    public:
        cpu_archs_t cpu_arch() const { return m_cpu_arch; }
        uint16_t cpu_level() const { return m_cpu_level; }
        uint16_t cpu_revision() const { return m_cpu_revision; }
        uint8_t num_cpus() const { return m_num_cpus; }
        uint8_t os_type() const { return m_os_type; }
        uint32_t os_ver_major() const { return m_os_ver_major; }
        uint32_t os_ver_minor() const { return m_os_ver_minor; }
        uint32_t os_build() const { return m_os_build; }
        uint32_t os_platform() const { return m_os_platform; }
        uint32_t ofs_service_pack() const { return m_ofs_service_pack; }
        uint16_t os_suite_mask() const { return m_os_suite_mask; }
        uint16_t reserved2() const { return m_reserved2; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::dir_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class exception_record_t : public kaitai::kstruct {

    public:

        exception_record_t(kaitai::kstream* p__io, windows_minidump_t::exception_stream_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~exception_record_t();

    private:
        uint32_t m_code;
        uint32_t m_flags;
        uint64_t m_inner_exception;
        uint64_t m_addr;
        uint32_t m_num_params;
        uint32_t m_reserved;
        std::vector<uint64_t>* m_params;
        windows_minidump_t* m__root;
        windows_minidump_t::exception_stream_t* m__parent;

    public:
        uint32_t code() const { return m_code; }
        uint32_t flags() const { return m_flags; }
        uint64_t inner_exception() const { return m_inner_exception; }

        /**
         * Memory address where exception has occurred
         */
        uint64_t addr() const { return m_addr; }
        uint32_t num_params() const { return m_num_params; }
        uint32_t reserved() const { return 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.
         */
        std::vector<uint64_t>* params() const { return m_params; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::exception_stream_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class misc_info_t : public kaitai::kstruct {

    public:

        misc_info_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~misc_info_t();

    private:
        uint32_t m_len_info;
        uint32_t m_flags1;
        uint32_t m_process_id;
        uint32_t m_process_create_time;
        uint32_t m_process_user_time;
        uint32_t m_process_kernel_time;
        uint32_t m_cpu_max_mhz;
        uint32_t m_cpu_cur_mhz;
        uint32_t m_cpu_limit_mhz;
        uint32_t m_cpu_max_idle_state;
        uint32_t m_cpu_cur_idle_state;
        windows_minidump_t* m__root;
        windows_minidump_t::dir_t* m__parent;

    public:
        uint32_t len_info() const { return m_len_info; }
        uint32_t flags1() const { return m_flags1; }
        uint32_t process_id() const { return m_process_id; }
        uint32_t process_create_time() const { return m_process_create_time; }
        uint32_t process_user_time() const { return m_process_user_time; }
        uint32_t process_kernel_time() const { return m_process_kernel_time; }
        uint32_t cpu_max_mhz() const { return m_cpu_max_mhz; }
        uint32_t cpu_cur_mhz() const { return m_cpu_cur_mhz; }
        uint32_t cpu_limit_mhz() const { return m_cpu_limit_mhz; }
        uint32_t cpu_max_idle_state() const { return m_cpu_max_idle_state; }
        uint32_t cpu_cur_idle_state() const { return m_cpu_cur_idle_state; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::dir_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class dir_t : public kaitai::kstruct {

    public:

        dir_t(kaitai::kstream* p__io, windows_minidump_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~dir_t();

    private:
        bool f_data;
        kaitai::kstruct* m_data;

    public:
        kaitai::kstruct* data();

    private:
        stream_types_t m_stream_type;
        uint32_t m_len_data;
        uint32_t m_ofs_data;
        windows_minidump_t* m__root;
        windows_minidump_t* m__parent;
        std::string m__raw_data;
        kaitai::kstream* m__io__raw_data;

    public:
        stream_types_t stream_type() const { return m_stream_type; }

        /**
         * \sa Source
         */
        uint32_t len_data() const { return m_len_data; }
        uint32_t ofs_data() const { return m_ofs_data; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t* _parent() const { return m__parent; }
        std::string _raw_data() const { return m__raw_data; }
        kaitai::kstream* _io__raw_data() const { return m__io__raw_data; }
    };

    /**
     * \sa Source
     */

    class thread_t : public kaitai::kstruct {

    public:

        thread_t(kaitai::kstream* p__io, windows_minidump_t::thread_list_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~thread_t();

    private:
        uint32_t m_thread_id;
        uint32_t m_suspend_count;
        uint32_t m_priority_class;
        uint32_t m_priority;
        uint64_t m_teb;
        memory_descriptor_t* m_stack;
        location_descriptor_t* m_thread_context;
        windows_minidump_t* m__root;
        windows_minidump_t::thread_list_t* m__parent;

    public:
        uint32_t thread_id() const { return m_thread_id; }
        uint32_t suspend_count() const { return m_suspend_count; }
        uint32_t priority_class() const { return m_priority_class; }
        uint32_t priority() const { return m_priority; }

        /**
         * Thread Environment Block
         */
        uint64_t teb() const { return m_teb; }
        memory_descriptor_t* stack() const { return m_stack; }
        location_descriptor_t* thread_context() const { return m_thread_context; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::thread_list_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class memory_list_t : public kaitai::kstruct {

    public:

        memory_list_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~memory_list_t();

    private:
        uint32_t m_num_mem_ranges;
        std::vector<memory_descriptor_t*>* m_mem_ranges;
        windows_minidump_t* m__root;
        windows_minidump_t::dir_t* m__parent;

    public:
        uint32_t num_mem_ranges() const { return m_num_mem_ranges; }
        std::vector<memory_descriptor_t*>* mem_ranges() const { return m_mem_ranges; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::dir_t* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class memory_descriptor_t : public kaitai::kstruct {

    public:

        memory_descriptor_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~memory_descriptor_t();

    private:
        uint64_t m_addr_memory_range;
        location_descriptor_t* m_memory;
        windows_minidump_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        uint64_t addr_memory_range() const { return m_addr_memory_range; }
        location_descriptor_t* memory() const { return m_memory; }
        windows_minidump_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    /**
     * \sa Source
     */

    class exception_stream_t : public kaitai::kstruct {

    public:

        exception_stream_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent = 0, windows_minidump_t* p__root = 0);

    private:
        void _read();

    public:
        ~exception_stream_t();

    private:
        uint32_t m_thread_id;
        uint32_t m_reserved;
        exception_record_t* m_exception_rec;
        location_descriptor_t* m_thread_context;
        windows_minidump_t* m__root;
        windows_minidump_t::dir_t* m__parent;

    public:
        uint32_t thread_id() const { return m_thread_id; }
        uint32_t reserved() const { return m_reserved; }
        exception_record_t* exception_rec() const { return m_exception_rec; }
        location_descriptor_t* thread_context() const { return m_thread_context; }
        windows_minidump_t* _root() const { return m__root; }
        windows_minidump_t::dir_t* _parent() const { return m__parent; }
    };

private:
    bool f_streams;
    std::vector<dir_t*>* m_streams;

public:
    std::vector<dir_t*>* streams();

private:
    std::string m_magic1;
    std::string m_magic2;
    uint16_t m_version;
    uint32_t m_num_streams;
    uint32_t m_ofs_streams;
    uint32_t m_checksum;
    uint32_t m_timestamp;
    uint64_t m_flags;
    windows_minidump_t* m__root;
    kaitai::kstruct* m__parent;

public:
    std::string magic1() const { return m_magic1; }
    std::string magic2() const { return m_magic2; }
    uint16_t version() const { return m_version; }
    uint32_t num_streams() const { return m_num_streams; }
    uint32_t ofs_streams() const { return m_ofs_streams; }
    uint32_t checksum() const { return m_checksum; }
    uint32_t timestamp() const { return m_timestamp; }
    uint64_t flags() const { return m_flags; }
    windows_minidump_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

#endif  // WINDOWS_MINIDUMP_H_

windows_minidump.cpp

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

#include "windows_minidump.h"



windows_minidump_t::windows_minidump_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    f_streams = false;
    _read();
}

void windows_minidump_t::_read() {
    m_magic1 = m__io->ensure_fixed_contents(std::string("\x4D\x44\x4D\x50", 4));
    m_magic2 = m__io->ensure_fixed_contents(std::string("\x93\xA7", 2));
    m_version = m__io->read_u2le();
    m_num_streams = m__io->read_u4le();
    m_ofs_streams = m__io->read_u4le();
    m_checksum = m__io->read_u4le();
    m_timestamp = m__io->read_u4le();
    m_flags = m__io->read_u8le();
}

windows_minidump_t::~windows_minidump_t() {
    if (f_streams) {
        for (std::vector<dir_t*>::iterator it = m_streams->begin(); it != m_streams->end(); ++it) {
            delete *it;
        }
        delete m_streams;
    }
}

windows_minidump_t::thread_list_t::thread_list_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::thread_list_t::_read() {
    m_num_threads = m__io->read_u4le();
    int l_threads = num_threads();
    m_threads = new std::vector<thread_t*>();
    m_threads->reserve(l_threads);
    for (int i = 0; i < l_threads; i++) {
        m_threads->push_back(new thread_t(m__io, this, m__root));
    }
}

windows_minidump_t::thread_list_t::~thread_list_t() {
    for (std::vector<thread_t*>::iterator it = m_threads->begin(); it != m_threads->end(); ++it) {
        delete *it;
    }
    delete m_threads;
}

windows_minidump_t::location_descriptor_t::location_descriptor_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_data = false;
    _read();
}

void windows_minidump_t::location_descriptor_t::_read() {
    m_len_data = m__io->read_u4le();
    m_ofs_data = m__io->read_u4le();
}

windows_minidump_t::location_descriptor_t::~location_descriptor_t() {
    if (f_data) {
    }
}

std::string windows_minidump_t::location_descriptor_t::data() {
    if (f_data)
        return m_data;
    kaitai::kstream *io = _root()->_io();
    std::streampos _pos = io->pos();
    io->seek(ofs_data());
    m_data = io->read_bytes(len_data());
    io->seek(_pos);
    f_data = true;
    return m_data;
}

windows_minidump_t::minidump_string_t::minidump_string_t(kaitai::kstream* p__io, windows_minidump_t::system_info_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::minidump_string_t::_read() {
    m_len_str = m__io->read_u4le();
    m_str = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_str()), std::string("UTF-16LE"));
}

windows_minidump_t::minidump_string_t::~minidump_string_t() {
}

windows_minidump_t::system_info_t::system_info_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_service_pack = false;
    _read();
}

void windows_minidump_t::system_info_t::_read() {
    m_cpu_arch = static_cast<windows_minidump_t::system_info_t::cpu_archs_t>(m__io->read_u2le());
    m_cpu_level = m__io->read_u2le();
    m_cpu_revision = m__io->read_u2le();
    m_num_cpus = m__io->read_u1();
    m_os_type = m__io->read_u1();
    m_os_ver_major = m__io->read_u4le();
    m_os_ver_minor = m__io->read_u4le();
    m_os_build = m__io->read_u4le();
    m_os_platform = m__io->read_u4le();
    m_ofs_service_pack = m__io->read_u4le();
    m_os_suite_mask = m__io->read_u2le();
    m_reserved2 = m__io->read_u2le();
}

windows_minidump_t::system_info_t::~system_info_t() {
    if (f_service_pack && !n_service_pack) {
        delete m_service_pack;
    }
}

windows_minidump_t::minidump_string_t* windows_minidump_t::system_info_t::service_pack() {
    if (f_service_pack)
        return m_service_pack;
    n_service_pack = true;
    if (ofs_service_pack() > 0) {
        n_service_pack = false;
        kaitai::kstream *io = _root()->_io();
        std::streampos _pos = io->pos();
        io->seek(ofs_service_pack());
        m_service_pack = new minidump_string_t(io, this, m__root);
        io->seek(_pos);
    }
    f_service_pack = true;
    return m_service_pack;
}

windows_minidump_t::exception_record_t::exception_record_t(kaitai::kstream* p__io, windows_minidump_t::exception_stream_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::exception_record_t::_read() {
    m_code = m__io->read_u4le();
    m_flags = m__io->read_u4le();
    m_inner_exception = m__io->read_u8le();
    m_addr = m__io->read_u8le();
    m_num_params = m__io->read_u4le();
    m_reserved = m__io->read_u4le();
    int l_params = 15;
    m_params = new std::vector<uint64_t>();
    m_params->reserve(l_params);
    for (int i = 0; i < l_params; i++) {
        m_params->push_back(m__io->read_u8le());
    }
}

windows_minidump_t::exception_record_t::~exception_record_t() {
    delete m_params;
}

windows_minidump_t::misc_info_t::misc_info_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::misc_info_t::_read() {
    m_len_info = m__io->read_u4le();
    m_flags1 = m__io->read_u4le();
    m_process_id = m__io->read_u4le();
    m_process_create_time = m__io->read_u4le();
    m_process_user_time = m__io->read_u4le();
    m_process_kernel_time = m__io->read_u4le();
    m_cpu_max_mhz = m__io->read_u4le();
    m_cpu_cur_mhz = m__io->read_u4le();
    m_cpu_limit_mhz = m__io->read_u4le();
    m_cpu_max_idle_state = m__io->read_u4le();
    m_cpu_cur_idle_state = m__io->read_u4le();
}

windows_minidump_t::misc_info_t::~misc_info_t() {
}

windows_minidump_t::dir_t::dir_t(kaitai::kstream* p__io, windows_minidump_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_data = false;
    _read();
}

void windows_minidump_t::dir_t::_read() {
    m_stream_type = static_cast<windows_minidump_t::stream_types_t>(m__io->read_u4le());
    m_len_data = m__io->read_u4le();
    m_ofs_data = m__io->read_u4le();
}

windows_minidump_t::dir_t::~dir_t() {
    if (f_data && !n_data) {
        delete m__io__raw_data;
        delete m_data;
    }
}

kaitai::kstruct* windows_minidump_t::dir_t::data() {
    if (f_data)
        return m_data;
    std::streampos _pos = m__io->pos();
    m__io->seek(ofs_data());
    n_data = true;
    switch (stream_type()) {
    case STREAM_TYPES_MISC_INFO: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new misc_info_t(m__io__raw_data, this, m__root);
        break;
    }
    case STREAM_TYPES_EXCEPTION: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new exception_stream_t(m__io__raw_data, this, m__root);
        break;
    }
    case STREAM_TYPES_MEMORY_LIST: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new memory_list_t(m__io__raw_data, this, m__root);
        break;
    }
    case STREAM_TYPES_SYSTEM_INFO: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new system_info_t(m__io__raw_data, this, m__root);
        break;
    }
    case STREAM_TYPES_THREAD_LIST: {
        n_data = false;
        m__raw_data = m__io->read_bytes(len_data());
        m__io__raw_data = new kaitai::kstream(m__raw_data);
        m_data = new thread_list_t(m__io__raw_data, this, m__root);
        break;
    }
    default: {
        m__raw_data = m__io->read_bytes(len_data());
        break;
    }
    }
    m__io->seek(_pos);
    f_data = true;
    return m_data;
}

windows_minidump_t::thread_t::thread_t(kaitai::kstream* p__io, windows_minidump_t::thread_list_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::thread_t::_read() {
    m_thread_id = m__io->read_u4le();
    m_suspend_count = m__io->read_u4le();
    m_priority_class = m__io->read_u4le();
    m_priority = m__io->read_u4le();
    m_teb = m__io->read_u8le();
    m_stack = new memory_descriptor_t(m__io, this, m__root);
    m_thread_context = new location_descriptor_t(m__io, this, m__root);
}

windows_minidump_t::thread_t::~thread_t() {
    delete m_stack;
    delete m_thread_context;
}

windows_minidump_t::memory_list_t::memory_list_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::memory_list_t::_read() {
    m_num_mem_ranges = m__io->read_u4le();
    int l_mem_ranges = num_mem_ranges();
    m_mem_ranges = new std::vector<memory_descriptor_t*>();
    m_mem_ranges->reserve(l_mem_ranges);
    for (int i = 0; i < l_mem_ranges; i++) {
        m_mem_ranges->push_back(new memory_descriptor_t(m__io, this, m__root));
    }
}

windows_minidump_t::memory_list_t::~memory_list_t() {
    for (std::vector<memory_descriptor_t*>::iterator it = m_mem_ranges->begin(); it != m_mem_ranges->end(); ++it) {
        delete *it;
    }
    delete m_mem_ranges;
}

windows_minidump_t::memory_descriptor_t::memory_descriptor_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::memory_descriptor_t::_read() {
    m_addr_memory_range = m__io->read_u8le();
    m_memory = new location_descriptor_t(m__io, this, m__root);
}

windows_minidump_t::memory_descriptor_t::~memory_descriptor_t() {
    delete m_memory;
}

windows_minidump_t::exception_stream_t::exception_stream_t(kaitai::kstream* p__io, windows_minidump_t::dir_t* p__parent, windows_minidump_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void windows_minidump_t::exception_stream_t::_read() {
    m_thread_id = m__io->read_u4le();
    m_reserved = m__io->read_u4le();
    m_exception_rec = new exception_record_t(m__io, this, m__root);
    m_thread_context = new location_descriptor_t(m__io, this, m__root);
}

windows_minidump_t::exception_stream_t::~exception_stream_t() {
    delete m_exception_rec;
    delete m_thread_context;
}

std::vector<windows_minidump_t::dir_t*>* windows_minidump_t::streams() {
    if (f_streams)
        return m_streams;
    std::streampos _pos = m__io->pos();
    m__io->seek(ofs_streams());
    int l_streams = num_streams();
    m_streams = new std::vector<dir_t*>();
    m_streams->reserve(l_streams);
    for (int i = 0; i < l_streams; i++) {
        m_streams->push_back(new dir_t(m__io, this, m__root));
    }
    m__io->seek(_pos);
    f_streams = true;
    return m_streams;
}