Microsoft PE (Portable Executable) file format: C++98/STL parsing library

Application

Microsoft Windows

File extension

["exe", "dll", "sys"]

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.7

References

This page hosts a formal specification of Microsoft PE (Portable Executable) file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All parsing code for C++98/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

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 local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.exe", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #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:
    microsoft_pe_t data(&ks);
    

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

data.mz() // => get mz

C++98/STL source code to parse Microsoft PE (Portable Executable) file format

microsoft_pe.h

#ifndef MICROSOFT_PE_H_
#define MICROSOFT_PE_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 < 9000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required"
#endif

/**
 * \sa https://learn.microsoft.com/en-us/windows/win32/debug/pe-format Source
 */

class microsoft_pe_t : public kaitai::kstruct {

public:
    class certificate_entry_t;
    class optional_header_windows_t;
    class optional_header_data_dirs_t;
    class data_dir_t;
    class coff_symbol_t;
    class pe_header_t;
    class optional_header_t;
    class section_t;
    class certificate_table_t;
    class mz_placeholder_t;
    class optional_header_std_t;
    class coff_header_t;
    class annoyingstring_t;

    enum pe_format_t {
        PE_FORMAT_ROM_IMAGE = 263,
        PE_FORMAT_PE32 = 267,
        PE_FORMAT_PE32_PLUS = 523
    };

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

private:
    void _read();
    void _clean_up();

public:
    ~microsoft_pe_t();

    /**
     * \sa https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#the-attribute-certificate-table-image-only Source
     */

    class certificate_entry_t : public kaitai::kstruct {

    public:

        enum certificate_revision_t {
            CERTIFICATE_REVISION_REVISION_1_0 = 256,
            CERTIFICATE_REVISION_REVISION_2_0 = 512
        };

        enum certificate_type_enum_t {
            CERTIFICATE_TYPE_ENUM_X509 = 1,
            CERTIFICATE_TYPE_ENUM_PKCS_SIGNED_DATA = 2,
            CERTIFICATE_TYPE_ENUM_RESERVED_1 = 3,
            CERTIFICATE_TYPE_ENUM_TS_STACK_SIGNED = 4
        };

        certificate_entry_t(kaitai::kstream* p__io, microsoft_pe_t::certificate_table_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~certificate_entry_t();

    private:
        uint32_t m_length;
        certificate_revision_t m_revision;
        certificate_type_enum_t m_certificate_type;
        std::string m_certificate_bytes;
        microsoft_pe_t* m__root;
        microsoft_pe_t::certificate_table_t* m__parent;

    public:

        /**
         * Specifies the length of the attribute certificate entry.
         */
        uint32_t length() const { return m_length; }

        /**
         * Contains the certificate version number.
         */
        certificate_revision_t revision() const { return m_revision; }

        /**
         * Specifies the type of content in bCertificate
         */
        certificate_type_enum_t certificate_type() const { return m_certificate_type; }

        /**
         * Contains a certificate, such as an Authenticode signature.
         */
        std::string certificate_bytes() const { return m_certificate_bytes; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::certificate_table_t* _parent() const { return m__parent; }
    };

    class optional_header_windows_t : public kaitai::kstruct {

    public:

        enum subsystem_enum_t {
            SUBSYSTEM_ENUM_UNKNOWN = 0,
            SUBSYSTEM_ENUM_NATIVE = 1,
            SUBSYSTEM_ENUM_WINDOWS_GUI = 2,
            SUBSYSTEM_ENUM_WINDOWS_CUI = 3,
            SUBSYSTEM_ENUM_POSIX_CUI = 7,
            SUBSYSTEM_ENUM_WINDOWS_CE_GUI = 9,
            SUBSYSTEM_ENUM_EFI_APPLICATION = 10,
            SUBSYSTEM_ENUM_EFI_BOOT_SERVICE_DRIVER = 11,
            SUBSYSTEM_ENUM_EFI_RUNTIME_DRIVER = 12,
            SUBSYSTEM_ENUM_EFI_ROM = 13,
            SUBSYSTEM_ENUM_XBOX = 14,
            SUBSYSTEM_ENUM_WINDOWS_BOOT_APPLICATION = 16
        };

        optional_header_windows_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~optional_header_windows_t();

    private:
        uint32_t m_image_base_32;
        bool n_image_base_32;

    public:
        bool _is_null_image_base_32() { image_base_32(); return n_image_base_32; };

    private:
        uint64_t m_image_base_64;
        bool n_image_base_64;

    public:
        bool _is_null_image_base_64() { image_base_64(); return n_image_base_64; };

    private:
        uint32_t m_section_alignment;
        uint32_t m_file_alignment;
        uint16_t m_major_operating_system_version;
        uint16_t m_minor_operating_system_version;
        uint16_t m_major_image_version;
        uint16_t m_minor_image_version;
        uint16_t m_major_subsystem_version;
        uint16_t m_minor_subsystem_version;
        uint32_t m_win32_version_value;
        uint32_t m_size_of_image;
        uint32_t m_size_of_headers;
        uint32_t m_check_sum;
        subsystem_enum_t m_subsystem;
        uint16_t m_dll_characteristics;
        uint32_t m_size_of_stack_reserve_32;
        bool n_size_of_stack_reserve_32;

    public:
        bool _is_null_size_of_stack_reserve_32() { size_of_stack_reserve_32(); return n_size_of_stack_reserve_32; };

    private:
        uint64_t m_size_of_stack_reserve_64;
        bool n_size_of_stack_reserve_64;

    public:
        bool _is_null_size_of_stack_reserve_64() { size_of_stack_reserve_64(); return n_size_of_stack_reserve_64; };

    private:
        uint32_t m_size_of_stack_commit_32;
        bool n_size_of_stack_commit_32;

    public:
        bool _is_null_size_of_stack_commit_32() { size_of_stack_commit_32(); return n_size_of_stack_commit_32; };

    private:
        uint64_t m_size_of_stack_commit_64;
        bool n_size_of_stack_commit_64;

    public:
        bool _is_null_size_of_stack_commit_64() { size_of_stack_commit_64(); return n_size_of_stack_commit_64; };

    private:
        uint32_t m_size_of_heap_reserve_32;
        bool n_size_of_heap_reserve_32;

    public:
        bool _is_null_size_of_heap_reserve_32() { size_of_heap_reserve_32(); return n_size_of_heap_reserve_32; };

    private:
        uint64_t m_size_of_heap_reserve_64;
        bool n_size_of_heap_reserve_64;

    public:
        bool _is_null_size_of_heap_reserve_64() { size_of_heap_reserve_64(); return n_size_of_heap_reserve_64; };

    private:
        uint32_t m_size_of_heap_commit_32;
        bool n_size_of_heap_commit_32;

    public:
        bool _is_null_size_of_heap_commit_32() { size_of_heap_commit_32(); return n_size_of_heap_commit_32; };

    private:
        uint64_t m_size_of_heap_commit_64;
        bool n_size_of_heap_commit_64;

    public:
        bool _is_null_size_of_heap_commit_64() { size_of_heap_commit_64(); return n_size_of_heap_commit_64; };

    private:
        uint32_t m_loader_flags;
        uint32_t m_number_of_rva_and_sizes;
        microsoft_pe_t* m__root;
        microsoft_pe_t::optional_header_t* m__parent;

    public:
        uint32_t image_base_32() const { return m_image_base_32; }
        uint64_t image_base_64() const { return m_image_base_64; }
        uint32_t section_alignment() const { return m_section_alignment; }
        uint32_t file_alignment() const { return m_file_alignment; }
        uint16_t major_operating_system_version() const { return m_major_operating_system_version; }
        uint16_t minor_operating_system_version() const { return m_minor_operating_system_version; }
        uint16_t major_image_version() const { return m_major_image_version; }
        uint16_t minor_image_version() const { return m_minor_image_version; }
        uint16_t major_subsystem_version() const { return m_major_subsystem_version; }
        uint16_t minor_subsystem_version() const { return m_minor_subsystem_version; }
        uint32_t win32_version_value() const { return m_win32_version_value; }
        uint32_t size_of_image() const { return m_size_of_image; }
        uint32_t size_of_headers() const { return m_size_of_headers; }
        uint32_t check_sum() const { return m_check_sum; }
        subsystem_enum_t subsystem() const { return m_subsystem; }
        uint16_t dll_characteristics() const { return m_dll_characteristics; }
        uint32_t size_of_stack_reserve_32() const { return m_size_of_stack_reserve_32; }
        uint64_t size_of_stack_reserve_64() const { return m_size_of_stack_reserve_64; }
        uint32_t size_of_stack_commit_32() const { return m_size_of_stack_commit_32; }
        uint64_t size_of_stack_commit_64() const { return m_size_of_stack_commit_64; }
        uint32_t size_of_heap_reserve_32() const { return m_size_of_heap_reserve_32; }
        uint64_t size_of_heap_reserve_64() const { return m_size_of_heap_reserve_64; }
        uint32_t size_of_heap_commit_32() const { return m_size_of_heap_commit_32; }
        uint64_t size_of_heap_commit_64() const { return m_size_of_heap_commit_64; }
        uint32_t loader_flags() const { return m_loader_flags; }
        uint32_t number_of_rva_and_sizes() const { return m_number_of_rva_and_sizes; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::optional_header_t* _parent() const { return m__parent; }
    };

    class optional_header_data_dirs_t : public kaitai::kstruct {

    public:

        optional_header_data_dirs_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~optional_header_data_dirs_t();

    private:
        data_dir_t* m_export_table;
        data_dir_t* m_import_table;
        data_dir_t* m_resource_table;
        data_dir_t* m_exception_table;
        data_dir_t* m_certificate_table;
        data_dir_t* m_base_relocation_table;
        data_dir_t* m_debug;
        data_dir_t* m_architecture;
        data_dir_t* m_global_ptr;
        data_dir_t* m_tls_table;
        data_dir_t* m_load_config_table;
        data_dir_t* m_bound_import;
        data_dir_t* m_iat;
        data_dir_t* m_delay_import_descriptor;
        data_dir_t* m_clr_runtime_header;
        microsoft_pe_t* m__root;
        microsoft_pe_t::optional_header_t* m__parent;

    public:
        data_dir_t* export_table() const { return m_export_table; }
        data_dir_t* import_table() const { return m_import_table; }
        data_dir_t* resource_table() const { return m_resource_table; }
        data_dir_t* exception_table() const { return m_exception_table; }
        data_dir_t* certificate_table() const { return m_certificate_table; }
        data_dir_t* base_relocation_table() const { return m_base_relocation_table; }
        data_dir_t* debug() const { return m_debug; }
        data_dir_t* architecture() const { return m_architecture; }
        data_dir_t* global_ptr() const { return m_global_ptr; }
        data_dir_t* tls_table() const { return m_tls_table; }
        data_dir_t* load_config_table() const { return m_load_config_table; }
        data_dir_t* bound_import() const { return m_bound_import; }
        data_dir_t* iat() const { return m_iat; }
        data_dir_t* delay_import_descriptor() const { return m_delay_import_descriptor; }
        data_dir_t* clr_runtime_header() const { return m_clr_runtime_header; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::optional_header_t* _parent() const { return m__parent; }
    };

    class data_dir_t : public kaitai::kstruct {

    public:

        data_dir_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_data_dirs_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~data_dir_t();

    private:
        uint32_t m_virtual_address;
        uint32_t m_size;
        microsoft_pe_t* m__root;
        microsoft_pe_t::optional_header_data_dirs_t* m__parent;

    public:
        uint32_t virtual_address() const { return m_virtual_address; }
        uint32_t size() const { return m_size; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::optional_header_data_dirs_t* _parent() const { return m__parent; }
    };

    class coff_symbol_t : public kaitai::kstruct {

    public:

        coff_symbol_t(kaitai::kstream* p__io, microsoft_pe_t::coff_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~coff_symbol_t();

    private:
        bool f_section;
        section_t* m_section;

    public:
        section_t* section();

    private:
        bool f_data;
        std::string m_data;

    public:
        std::string data();

    private:
        annoyingstring_t* m_name_annoying;
        uint32_t m_value;
        uint16_t m_section_number;
        uint16_t m_type;
        uint8_t m_storage_class;
        uint8_t m_number_of_aux_symbols;
        microsoft_pe_t* m__root;
        microsoft_pe_t::coff_header_t* m__parent;
        std::string m__raw_name_annoying;
        kaitai::kstream* m__io__raw_name_annoying;

    public:
        annoyingstring_t* name_annoying() const { return m_name_annoying; }
        uint32_t value() const { return m_value; }
        uint16_t section_number() const { return m_section_number; }
        uint16_t type() const { return m_type; }
        uint8_t storage_class() const { return m_storage_class; }
        uint8_t number_of_aux_symbols() const { return m_number_of_aux_symbols; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::coff_header_t* _parent() const { return m__parent; }
        std::string _raw_name_annoying() const { return m__raw_name_annoying; }
        kaitai::kstream* _io__raw_name_annoying() const { return m__io__raw_name_annoying; }
    };

    class pe_header_t : public kaitai::kstruct {

    public:

        pe_header_t(kaitai::kstream* p__io, microsoft_pe_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~pe_header_t();

    private:
        bool f_certificate_table;
        certificate_table_t* m_certificate_table;
        bool n_certificate_table;

    public:
        bool _is_null_certificate_table() { certificate_table(); return n_certificate_table; };

    private:

    public:
        certificate_table_t* certificate_table();

    private:
        std::string m_pe_signature;
        coff_header_t* m_coff_hdr;
        optional_header_t* m_optional_hdr;
        std::vector<section_t*>* m_sections;
        microsoft_pe_t* m__root;
        microsoft_pe_t* m__parent;
        std::string m__raw_optional_hdr;
        kaitai::kstream* m__io__raw_optional_hdr;
        std::string m__raw_certificate_table;
        bool n__raw_certificate_table;

    public:
        bool _is_null__raw_certificate_table() { _raw_certificate_table(); return n__raw_certificate_table; };

    private:
        kaitai::kstream* m__io__raw_certificate_table;

    public:
        std::string pe_signature() const { return m_pe_signature; }
        coff_header_t* coff_hdr() const { return m_coff_hdr; }
        optional_header_t* optional_hdr() const { return m_optional_hdr; }
        std::vector<section_t*>* sections() const { return m_sections; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t* _parent() const { return m__parent; }
        std::string _raw_optional_hdr() const { return m__raw_optional_hdr; }
        kaitai::kstream* _io__raw_optional_hdr() const { return m__io__raw_optional_hdr; }
        std::string _raw_certificate_table() const { return m__raw_certificate_table; }
        kaitai::kstream* _io__raw_certificate_table() const { return m__io__raw_certificate_table; }
    };

    class optional_header_t : public kaitai::kstruct {

    public:

        optional_header_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~optional_header_t();

    private:
        optional_header_std_t* m_std;
        optional_header_windows_t* m_windows;
        optional_header_data_dirs_t* m_data_dirs;
        microsoft_pe_t* m__root;
        microsoft_pe_t::pe_header_t* m__parent;

    public:
        optional_header_std_t* std() const { return m_std; }
        optional_header_windows_t* windows() const { return m_windows; }
        optional_header_data_dirs_t* data_dirs() const { return m_data_dirs; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::pe_header_t* _parent() const { return m__parent; }
    };

    class section_t : public kaitai::kstruct {

    public:

        section_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~section_t();

    private:
        bool f_body;
        std::string m_body;

    public:
        std::string body();

    private:
        std::string m_name;
        uint32_t m_virtual_size;
        uint32_t m_virtual_address;
        uint32_t m_size_of_raw_data;
        uint32_t m_pointer_to_raw_data;
        uint32_t m_pointer_to_relocations;
        uint32_t m_pointer_to_linenumbers;
        uint16_t m_number_of_relocations;
        uint16_t m_number_of_linenumbers;
        uint32_t m_characteristics;
        microsoft_pe_t* m__root;
        microsoft_pe_t::pe_header_t* m__parent;

    public:
        std::string name() const { return m_name; }
        uint32_t virtual_size() const { return m_virtual_size; }
        uint32_t virtual_address() const { return m_virtual_address; }
        uint32_t size_of_raw_data() const { return m_size_of_raw_data; }
        uint32_t pointer_to_raw_data() const { return m_pointer_to_raw_data; }
        uint32_t pointer_to_relocations() const { return m_pointer_to_relocations; }
        uint32_t pointer_to_linenumbers() const { return m_pointer_to_linenumbers; }
        uint16_t number_of_relocations() const { return m_number_of_relocations; }
        uint16_t number_of_linenumbers() const { return m_number_of_linenumbers; }
        uint32_t characteristics() const { return m_characteristics; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::pe_header_t* _parent() const { return m__parent; }
    };

    class certificate_table_t : public kaitai::kstruct {

    public:

        certificate_table_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~certificate_table_t();

    private:
        std::vector<certificate_entry_t*>* m_items;
        microsoft_pe_t* m__root;
        microsoft_pe_t::pe_header_t* m__parent;

    public:
        std::vector<certificate_entry_t*>* items() const { return m_items; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::pe_header_t* _parent() const { return m__parent; }
    };

    class mz_placeholder_t : public kaitai::kstruct {

    public:

        mz_placeholder_t(kaitai::kstream* p__io, microsoft_pe_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~mz_placeholder_t();

    private:
        std::string m_magic;
        std::string m_data1;
        uint32_t m_ofs_pe;
        microsoft_pe_t* m__root;
        microsoft_pe_t* m__parent;

    public:
        std::string magic() const { return m_magic; }
        std::string data1() const { return m_data1; }

        /**
         * In PE file, an offset to PE header
         */
        uint32_t ofs_pe() const { return m_ofs_pe; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t* _parent() const { return m__parent; }
    };

    class optional_header_std_t : public kaitai::kstruct {

    public:

        optional_header_std_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~optional_header_std_t();

    private:
        pe_format_t m_format;
        uint8_t m_major_linker_version;
        uint8_t m_minor_linker_version;
        uint32_t m_size_of_code;
        uint32_t m_size_of_initialized_data;
        uint32_t m_size_of_uninitialized_data;
        uint32_t m_address_of_entry_point;
        uint32_t m_base_of_code;
        uint32_t m_base_of_data;
        bool n_base_of_data;

    public:
        bool _is_null_base_of_data() { base_of_data(); return n_base_of_data; };

    private:
        microsoft_pe_t* m__root;
        microsoft_pe_t::optional_header_t* m__parent;

    public:
        pe_format_t format() const { return m_format; }
        uint8_t major_linker_version() const { return m_major_linker_version; }
        uint8_t minor_linker_version() const { return m_minor_linker_version; }
        uint32_t size_of_code() const { return m_size_of_code; }
        uint32_t size_of_initialized_data() const { return m_size_of_initialized_data; }
        uint32_t size_of_uninitialized_data() const { return m_size_of_uninitialized_data; }
        uint32_t address_of_entry_point() const { return m_address_of_entry_point; }
        uint32_t base_of_code() const { return m_base_of_code; }
        uint32_t base_of_data() const { return m_base_of_data; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::optional_header_t* _parent() const { return m__parent; }
    };

    /**
     * \sa 3.3. COFF File Header (Object and Image)
     */

    class coff_header_t : public kaitai::kstruct {

    public:

        enum machine_type_t {
            MACHINE_TYPE_UNKNOWN = 0,
            MACHINE_TYPE_I386 = 332,
            MACHINE_TYPE_R4000 = 358,
            MACHINE_TYPE_WCE_MIPS_V2 = 361,
            MACHINE_TYPE_ALPHA = 388,
            MACHINE_TYPE_SH3 = 418,
            MACHINE_TYPE_SH3_DSP = 419,
            MACHINE_TYPE_SH4 = 422,
            MACHINE_TYPE_SH5 = 424,
            MACHINE_TYPE_ARM = 448,
            MACHINE_TYPE_THUMB = 450,
            MACHINE_TYPE_ARM_NT = 452,
            MACHINE_TYPE_AM33 = 467,
            MACHINE_TYPE_POWERPC = 496,
            MACHINE_TYPE_POWERPC_FP = 497,
            MACHINE_TYPE_IA64 = 512,
            MACHINE_TYPE_MIPS16 = 614,
            MACHINE_TYPE_ALPHA64_OR_AXP64 = 644,
            MACHINE_TYPE_MIPS_FPU = 870,
            MACHINE_TYPE_MIPS16_FPU = 1126,
            MACHINE_TYPE_EBC = 3772,
            MACHINE_TYPE_RISCV32 = 20530,
            MACHINE_TYPE_RISCV64 = 20580,
            MACHINE_TYPE_RISCV128 = 20776,
            MACHINE_TYPE_LOONGARCH32 = 25138,
            MACHINE_TYPE_LOONGARCH64 = 25188,
            MACHINE_TYPE_AMD64 = 34404,
            MACHINE_TYPE_M32R = 36929,
            MACHINE_TYPE_ARM64 = 43620
        };

        coff_header_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~coff_header_t();

    private:
        bool f_symbol_table_size;
        int32_t m_symbol_table_size;

    public:
        int32_t symbol_table_size();

    private:
        bool f_symbol_name_table_offset;
        int32_t m_symbol_name_table_offset;

    public:
        int32_t symbol_name_table_offset();

    private:
        bool f_symbol_name_table_size;
        uint32_t m_symbol_name_table_size;

    public:
        uint32_t symbol_name_table_size();

    private:
        bool f_symbol_table;
        std::vector<coff_symbol_t*>* m_symbol_table;

    public:
        std::vector<coff_symbol_t*>* symbol_table();

    private:
        machine_type_t m_machine;
        uint16_t m_number_of_sections;
        uint32_t m_time_date_stamp;
        uint32_t m_pointer_to_symbol_table;
        uint32_t m_number_of_symbols;
        uint16_t m_size_of_optional_header;
        uint16_t m_characteristics;
        microsoft_pe_t* m__root;
        microsoft_pe_t::pe_header_t* m__parent;

    public:
        machine_type_t machine() const { return m_machine; }
        uint16_t number_of_sections() const { return m_number_of_sections; }
        uint32_t time_date_stamp() const { return m_time_date_stamp; }
        uint32_t pointer_to_symbol_table() const { return m_pointer_to_symbol_table; }
        uint32_t number_of_symbols() const { return m_number_of_symbols; }
        uint16_t size_of_optional_header() const { return m_size_of_optional_header; }
        uint16_t characteristics() const { return m_characteristics; }
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::pe_header_t* _parent() const { return m__parent; }
    };

    class annoyingstring_t : public kaitai::kstruct {

    public:

        annoyingstring_t(kaitai::kstream* p__io, microsoft_pe_t::coff_symbol_t* p__parent = 0, microsoft_pe_t* p__root = 0);

    private:
        void _read();
        void _clean_up();

    public:
        ~annoyingstring_t();

    private:
        bool f_name_from_offset;
        std::string m_name_from_offset;
        bool n_name_from_offset;

    public:
        bool _is_null_name_from_offset() { name_from_offset(); return n_name_from_offset; };

    private:

    public:
        std::string name_from_offset();

    private:
        bool f_name_offset;
        uint32_t m_name_offset;

    public:
        uint32_t name_offset();

    private:
        bool f_name;
        std::string m_name;

    public:
        std::string name();

    private:
        bool f_name_zeroes;
        uint32_t m_name_zeroes;

    public:
        uint32_t name_zeroes();

    private:
        bool f_name_from_short;
        std::string m_name_from_short;
        bool n_name_from_short;

    public:
        bool _is_null_name_from_short() { name_from_short(); return n_name_from_short; };

    private:

    public:
        std::string name_from_short();

    private:
        microsoft_pe_t* m__root;
        microsoft_pe_t::coff_symbol_t* m__parent;

    public:
        microsoft_pe_t* _root() const { return m__root; }
        microsoft_pe_t::coff_symbol_t* _parent() const { return m__parent; }
    };

private:
    bool f_pe;
    pe_header_t* m_pe;

public:
    pe_header_t* pe();

private:
    mz_placeholder_t* m_mz;
    microsoft_pe_t* m__root;
    kaitai::kstruct* m__parent;

public:
    mz_placeholder_t* mz() const { return m_mz; }
    microsoft_pe_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

#endif  // MICROSOFT_PE_H_

microsoft_pe.cpp

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

#include "microsoft_pe.h"
#include "kaitai/exceptions.h"

microsoft_pe_t::microsoft_pe_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    m_mz = 0;
    m_pe = 0;
    f_pe = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::_read() {
    m_mz = new mz_placeholder_t(m__io, this, m__root);
}

microsoft_pe_t::~microsoft_pe_t() {
    _clean_up();
}

void microsoft_pe_t::_clean_up() {
    if (m_mz) {
        delete m_mz; m_mz = 0;
    }
    if (f_pe) {
        if (m_pe) {
            delete m_pe; m_pe = 0;
        }
    }
}

microsoft_pe_t::certificate_entry_t::certificate_entry_t(kaitai::kstream* p__io, microsoft_pe_t::certificate_table_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::certificate_entry_t::_read() {
    m_length = m__io->read_u4le();
    m_revision = static_cast<microsoft_pe_t::certificate_entry_t::certificate_revision_t>(m__io->read_u2le());
    m_certificate_type = static_cast<microsoft_pe_t::certificate_entry_t::certificate_type_enum_t>(m__io->read_u2le());
    m_certificate_bytes = m__io->read_bytes((length() - 8));
}

microsoft_pe_t::certificate_entry_t::~certificate_entry_t() {
    _clean_up();
}

void microsoft_pe_t::certificate_entry_t::_clean_up() {
}

microsoft_pe_t::optional_header_windows_t::optional_header_windows_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::optional_header_windows_t::_read() {
    n_image_base_32 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_image_base_32 = false;
        m_image_base_32 = m__io->read_u4le();
    }
    n_image_base_64 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32_PLUS) {
        n_image_base_64 = false;
        m_image_base_64 = m__io->read_u8le();
    }
    m_section_alignment = m__io->read_u4le();
    m_file_alignment = m__io->read_u4le();
    m_major_operating_system_version = m__io->read_u2le();
    m_minor_operating_system_version = m__io->read_u2le();
    m_major_image_version = m__io->read_u2le();
    m_minor_image_version = m__io->read_u2le();
    m_major_subsystem_version = m__io->read_u2le();
    m_minor_subsystem_version = m__io->read_u2le();
    m_win32_version_value = m__io->read_u4le();
    m_size_of_image = m__io->read_u4le();
    m_size_of_headers = m__io->read_u4le();
    m_check_sum = m__io->read_u4le();
    m_subsystem = static_cast<microsoft_pe_t::optional_header_windows_t::subsystem_enum_t>(m__io->read_u2le());
    m_dll_characteristics = m__io->read_u2le();
    n_size_of_stack_reserve_32 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_size_of_stack_reserve_32 = false;
        m_size_of_stack_reserve_32 = m__io->read_u4le();
    }
    n_size_of_stack_reserve_64 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32_PLUS) {
        n_size_of_stack_reserve_64 = false;
        m_size_of_stack_reserve_64 = m__io->read_u8le();
    }
    n_size_of_stack_commit_32 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_size_of_stack_commit_32 = false;
        m_size_of_stack_commit_32 = m__io->read_u4le();
    }
    n_size_of_stack_commit_64 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32_PLUS) {
        n_size_of_stack_commit_64 = false;
        m_size_of_stack_commit_64 = m__io->read_u8le();
    }
    n_size_of_heap_reserve_32 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_size_of_heap_reserve_32 = false;
        m_size_of_heap_reserve_32 = m__io->read_u4le();
    }
    n_size_of_heap_reserve_64 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32_PLUS) {
        n_size_of_heap_reserve_64 = false;
        m_size_of_heap_reserve_64 = m__io->read_u8le();
    }
    n_size_of_heap_commit_32 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_size_of_heap_commit_32 = false;
        m_size_of_heap_commit_32 = m__io->read_u4le();
    }
    n_size_of_heap_commit_64 = true;
    if (_parent()->std()->format() == microsoft_pe_t::PE_FORMAT_PE32_PLUS) {
        n_size_of_heap_commit_64 = false;
        m_size_of_heap_commit_64 = m__io->read_u8le();
    }
    m_loader_flags = m__io->read_u4le();
    m_number_of_rva_and_sizes = m__io->read_u4le();
}

microsoft_pe_t::optional_header_windows_t::~optional_header_windows_t() {
    _clean_up();
}

void microsoft_pe_t::optional_header_windows_t::_clean_up() {
    if (!n_image_base_32) {
    }
    if (!n_image_base_64) {
    }
    if (!n_size_of_stack_reserve_32) {
    }
    if (!n_size_of_stack_reserve_64) {
    }
    if (!n_size_of_stack_commit_32) {
    }
    if (!n_size_of_stack_commit_64) {
    }
    if (!n_size_of_heap_reserve_32) {
    }
    if (!n_size_of_heap_reserve_64) {
    }
    if (!n_size_of_heap_commit_32) {
    }
    if (!n_size_of_heap_commit_64) {
    }
}

microsoft_pe_t::optional_header_data_dirs_t::optional_header_data_dirs_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_export_table = 0;
    m_import_table = 0;
    m_resource_table = 0;
    m_exception_table = 0;
    m_certificate_table = 0;
    m_base_relocation_table = 0;
    m_debug = 0;
    m_architecture = 0;
    m_global_ptr = 0;
    m_tls_table = 0;
    m_load_config_table = 0;
    m_bound_import = 0;
    m_iat = 0;
    m_delay_import_descriptor = 0;
    m_clr_runtime_header = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::optional_header_data_dirs_t::_read() {
    m_export_table = new data_dir_t(m__io, this, m__root);
    m_import_table = new data_dir_t(m__io, this, m__root);
    m_resource_table = new data_dir_t(m__io, this, m__root);
    m_exception_table = new data_dir_t(m__io, this, m__root);
    m_certificate_table = new data_dir_t(m__io, this, m__root);
    m_base_relocation_table = new data_dir_t(m__io, this, m__root);
    m_debug = new data_dir_t(m__io, this, m__root);
    m_architecture = new data_dir_t(m__io, this, m__root);
    m_global_ptr = new data_dir_t(m__io, this, m__root);
    m_tls_table = new data_dir_t(m__io, this, m__root);
    m_load_config_table = new data_dir_t(m__io, this, m__root);
    m_bound_import = new data_dir_t(m__io, this, m__root);
    m_iat = new data_dir_t(m__io, this, m__root);
    m_delay_import_descriptor = new data_dir_t(m__io, this, m__root);
    m_clr_runtime_header = new data_dir_t(m__io, this, m__root);
}

microsoft_pe_t::optional_header_data_dirs_t::~optional_header_data_dirs_t() {
    _clean_up();
}

void microsoft_pe_t::optional_header_data_dirs_t::_clean_up() {
    if (m_export_table) {
        delete m_export_table; m_export_table = 0;
    }
    if (m_import_table) {
        delete m_import_table; m_import_table = 0;
    }
    if (m_resource_table) {
        delete m_resource_table; m_resource_table = 0;
    }
    if (m_exception_table) {
        delete m_exception_table; m_exception_table = 0;
    }
    if (m_certificate_table) {
        delete m_certificate_table; m_certificate_table = 0;
    }
    if (m_base_relocation_table) {
        delete m_base_relocation_table; m_base_relocation_table = 0;
    }
    if (m_debug) {
        delete m_debug; m_debug = 0;
    }
    if (m_architecture) {
        delete m_architecture; m_architecture = 0;
    }
    if (m_global_ptr) {
        delete m_global_ptr; m_global_ptr = 0;
    }
    if (m_tls_table) {
        delete m_tls_table; m_tls_table = 0;
    }
    if (m_load_config_table) {
        delete m_load_config_table; m_load_config_table = 0;
    }
    if (m_bound_import) {
        delete m_bound_import; m_bound_import = 0;
    }
    if (m_iat) {
        delete m_iat; m_iat = 0;
    }
    if (m_delay_import_descriptor) {
        delete m_delay_import_descriptor; m_delay_import_descriptor = 0;
    }
    if (m_clr_runtime_header) {
        delete m_clr_runtime_header; m_clr_runtime_header = 0;
    }
}

microsoft_pe_t::data_dir_t::data_dir_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_data_dirs_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::data_dir_t::_read() {
    m_virtual_address = m__io->read_u4le();
    m_size = m__io->read_u4le();
}

microsoft_pe_t::data_dir_t::~data_dir_t() {
    _clean_up();
}

void microsoft_pe_t::data_dir_t::_clean_up() {
}

microsoft_pe_t::coff_symbol_t::coff_symbol_t(kaitai::kstream* p__io, microsoft_pe_t::coff_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_name_annoying = 0;
    m__io__raw_name_annoying = 0;
    f_section = false;
    f_data = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::coff_symbol_t::_read() {
    m__raw_name_annoying = m__io->read_bytes(8);
    m__io__raw_name_annoying = new kaitai::kstream(m__raw_name_annoying);
    m_name_annoying = new annoyingstring_t(m__io__raw_name_annoying, this, m__root);
    m_value = m__io->read_u4le();
    m_section_number = m__io->read_u2le();
    m_type = m__io->read_u2le();
    m_storage_class = m__io->read_u1();
    m_number_of_aux_symbols = m__io->read_u1();
}

microsoft_pe_t::coff_symbol_t::~coff_symbol_t() {
    _clean_up();
}

void microsoft_pe_t::coff_symbol_t::_clean_up() {
    if (m__io__raw_name_annoying) {
        delete m__io__raw_name_annoying; m__io__raw_name_annoying = 0;
    }
    if (m_name_annoying) {
        delete m_name_annoying; m_name_annoying = 0;
    }
    if (f_data) {
    }
}

microsoft_pe_t::section_t* microsoft_pe_t::coff_symbol_t::section() {
    if (f_section)
        return m_section;
    m_section = _root()->pe()->sections()->at((section_number() - 1));
    f_section = true;
    return m_section;
}

std::string microsoft_pe_t::coff_symbol_t::data() {
    if (f_data)
        return m_data;
    std::streampos _pos = m__io->pos();
    m__io->seek((section()->pointer_to_raw_data() + value()));
    m_data = m__io->read_bytes(1);
    m__io->seek(_pos);
    f_data = true;
    return m_data;
}

microsoft_pe_t::pe_header_t::pe_header_t(kaitai::kstream* p__io, microsoft_pe_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_coff_hdr = 0;
    m_optional_hdr = 0;
    m__io__raw_optional_hdr = 0;
    m_sections = 0;
    m_certificate_table = 0;
    m__io__raw_certificate_table = 0;
    f_certificate_table = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::pe_header_t::_read() {
    m_pe_signature = m__io->read_bytes(4);
    if (!(pe_signature() == std::string("\x50\x45\x00\x00", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x50\x45\x00\x00", 4), pe_signature(), _io(), std::string("/types/pe_header/seq/0"));
    }
    m_coff_hdr = new coff_header_t(m__io, this, m__root);
    m__raw_optional_hdr = m__io->read_bytes(coff_hdr()->size_of_optional_header());
    m__io__raw_optional_hdr = new kaitai::kstream(m__raw_optional_hdr);
    m_optional_hdr = new optional_header_t(m__io__raw_optional_hdr, this, m__root);
    m_sections = new std::vector<section_t*>();
    const int l_sections = coff_hdr()->number_of_sections();
    for (int i = 0; i < l_sections; i++) {
        m_sections->push_back(new section_t(m__io, this, m__root));
    }
}

microsoft_pe_t::pe_header_t::~pe_header_t() {
    _clean_up();
}

void microsoft_pe_t::pe_header_t::_clean_up() {
    if (m_coff_hdr) {
        delete m_coff_hdr; m_coff_hdr = 0;
    }
    if (m__io__raw_optional_hdr) {
        delete m__io__raw_optional_hdr; m__io__raw_optional_hdr = 0;
    }
    if (m_optional_hdr) {
        delete m_optional_hdr; m_optional_hdr = 0;
    }
    if (m_sections) {
        for (std::vector<section_t*>::iterator it = m_sections->begin(); it != m_sections->end(); ++it) {
            delete *it;
        }
        delete m_sections; m_sections = 0;
    }
    if (f_certificate_table && !n_certificate_table) {
        if (m__io__raw_certificate_table) {
            delete m__io__raw_certificate_table; m__io__raw_certificate_table = 0;
        }
        if (m_certificate_table) {
            delete m_certificate_table; m_certificate_table = 0;
        }
    }
}

microsoft_pe_t::certificate_table_t* microsoft_pe_t::pe_header_t::certificate_table() {
    if (f_certificate_table)
        return m_certificate_table;
    n_certificate_table = true;
    if (optional_hdr()->data_dirs()->certificate_table()->virtual_address() != 0) {
        n_certificate_table = false;
        std::streampos _pos = m__io->pos();
        m__io->seek(optional_hdr()->data_dirs()->certificate_table()->virtual_address());
        m__raw_certificate_table = m__io->read_bytes(optional_hdr()->data_dirs()->certificate_table()->size());
        m__io__raw_certificate_table = new kaitai::kstream(m__raw_certificate_table);
        m_certificate_table = new certificate_table_t(m__io__raw_certificate_table, this, m__root);
        m__io->seek(_pos);
        f_certificate_table = true;
    }
    return m_certificate_table;
}

microsoft_pe_t::optional_header_t::optional_header_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_std = 0;
    m_windows = 0;
    m_data_dirs = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::optional_header_t::_read() {
    m_std = new optional_header_std_t(m__io, this, m__root);
    m_windows = new optional_header_windows_t(m__io, this, m__root);
    m_data_dirs = new optional_header_data_dirs_t(m__io, this, m__root);
}

microsoft_pe_t::optional_header_t::~optional_header_t() {
    _clean_up();
}

void microsoft_pe_t::optional_header_t::_clean_up() {
    if (m_std) {
        delete m_std; m_std = 0;
    }
    if (m_windows) {
        delete m_windows; m_windows = 0;
    }
    if (m_data_dirs) {
        delete m_data_dirs; m_data_dirs = 0;
    }
}

microsoft_pe_t::section_t::section_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_body = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::section_t::_read() {
    m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_strip_right(m__io->read_bytes(8), 0), std::string("UTF-8"));
    m_virtual_size = m__io->read_u4le();
    m_virtual_address = m__io->read_u4le();
    m_size_of_raw_data = m__io->read_u4le();
    m_pointer_to_raw_data = m__io->read_u4le();
    m_pointer_to_relocations = m__io->read_u4le();
    m_pointer_to_linenumbers = m__io->read_u4le();
    m_number_of_relocations = m__io->read_u2le();
    m_number_of_linenumbers = m__io->read_u2le();
    m_characteristics = m__io->read_u4le();
}

microsoft_pe_t::section_t::~section_t() {
    _clean_up();
}

void microsoft_pe_t::section_t::_clean_up() {
    if (f_body) {
    }
}

std::string microsoft_pe_t::section_t::body() {
    if (f_body)
        return m_body;
    std::streampos _pos = m__io->pos();
    m__io->seek(pointer_to_raw_data());
    m_body = m__io->read_bytes(size_of_raw_data());
    m__io->seek(_pos);
    f_body = true;
    return m_body;
}

microsoft_pe_t::certificate_table_t::certificate_table_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_items = 0;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::certificate_table_t::_read() {
    m_items = new std::vector<certificate_entry_t*>();
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_items->push_back(new certificate_entry_t(m__io, this, m__root));
            i++;
        }
    }
}

microsoft_pe_t::certificate_table_t::~certificate_table_t() {
    _clean_up();
}

void microsoft_pe_t::certificate_table_t::_clean_up() {
    if (m_items) {
        for (std::vector<certificate_entry_t*>::iterator it = m_items->begin(); it != m_items->end(); ++it) {
            delete *it;
        }
        delete m_items; m_items = 0;
    }
}

microsoft_pe_t::mz_placeholder_t::mz_placeholder_t(kaitai::kstream* p__io, microsoft_pe_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::mz_placeholder_t::_read() {
    m_magic = m__io->read_bytes(2);
    if (!(magic() == std::string("\x4D\x5A", 2))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x4D\x5A", 2), magic(), _io(), std::string("/types/mz_placeholder/seq/0"));
    }
    m_data1 = m__io->read_bytes(58);
    m_ofs_pe = m__io->read_u4le();
}

microsoft_pe_t::mz_placeholder_t::~mz_placeholder_t() {
    _clean_up();
}

void microsoft_pe_t::mz_placeholder_t::_clean_up() {
}

microsoft_pe_t::optional_header_std_t::optional_header_std_t(kaitai::kstream* p__io, microsoft_pe_t::optional_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::optional_header_std_t::_read() {
    m_format = static_cast<microsoft_pe_t::pe_format_t>(m__io->read_u2le());
    m_major_linker_version = m__io->read_u1();
    m_minor_linker_version = m__io->read_u1();
    m_size_of_code = m__io->read_u4le();
    m_size_of_initialized_data = m__io->read_u4le();
    m_size_of_uninitialized_data = m__io->read_u4le();
    m_address_of_entry_point = m__io->read_u4le();
    m_base_of_code = m__io->read_u4le();
    n_base_of_data = true;
    if (format() == microsoft_pe_t::PE_FORMAT_PE32) {
        n_base_of_data = false;
        m_base_of_data = m__io->read_u4le();
    }
}

microsoft_pe_t::optional_header_std_t::~optional_header_std_t() {
    _clean_up();
}

void microsoft_pe_t::optional_header_std_t::_clean_up() {
    if (!n_base_of_data) {
    }
}

microsoft_pe_t::coff_header_t::coff_header_t(kaitai::kstream* p__io, microsoft_pe_t::pe_header_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m_symbol_table = 0;
    f_symbol_table_size = false;
    f_symbol_name_table_offset = false;
    f_symbol_name_table_size = false;
    f_symbol_table = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::coff_header_t::_read() {
    m_machine = static_cast<microsoft_pe_t::coff_header_t::machine_type_t>(m__io->read_u2le());
    m_number_of_sections = m__io->read_u2le();
    m_time_date_stamp = m__io->read_u4le();
    m_pointer_to_symbol_table = m__io->read_u4le();
    m_number_of_symbols = m__io->read_u4le();
    m_size_of_optional_header = m__io->read_u2le();
    m_characteristics = m__io->read_u2le();
}

microsoft_pe_t::coff_header_t::~coff_header_t() {
    _clean_up();
}

void microsoft_pe_t::coff_header_t::_clean_up() {
    if (f_symbol_name_table_size) {
    }
    if (f_symbol_table) {
        if (m_symbol_table) {
            for (std::vector<coff_symbol_t*>::iterator it = m_symbol_table->begin(); it != m_symbol_table->end(); ++it) {
                delete *it;
            }
            delete m_symbol_table; m_symbol_table = 0;
        }
    }
}

int32_t microsoft_pe_t::coff_header_t::symbol_table_size() {
    if (f_symbol_table_size)
        return m_symbol_table_size;
    m_symbol_table_size = (number_of_symbols() * 18);
    f_symbol_table_size = true;
    return m_symbol_table_size;
}

int32_t microsoft_pe_t::coff_header_t::symbol_name_table_offset() {
    if (f_symbol_name_table_offset)
        return m_symbol_name_table_offset;
    m_symbol_name_table_offset = (pointer_to_symbol_table() + symbol_table_size());
    f_symbol_name_table_offset = true;
    return m_symbol_name_table_offset;
}

uint32_t microsoft_pe_t::coff_header_t::symbol_name_table_size() {
    if (f_symbol_name_table_size)
        return m_symbol_name_table_size;
    std::streampos _pos = m__io->pos();
    m__io->seek(symbol_name_table_offset());
    m_symbol_name_table_size = m__io->read_u4le();
    m__io->seek(_pos);
    f_symbol_name_table_size = true;
    return m_symbol_name_table_size;
}

std::vector<microsoft_pe_t::coff_symbol_t*>* microsoft_pe_t::coff_header_t::symbol_table() {
    if (f_symbol_table)
        return m_symbol_table;
    std::streampos _pos = m__io->pos();
    m__io->seek(pointer_to_symbol_table());
    m_symbol_table = new std::vector<coff_symbol_t*>();
    const int l_symbol_table = number_of_symbols();
    for (int i = 0; i < l_symbol_table; i++) {
        m_symbol_table->push_back(new coff_symbol_t(m__io, this, m__root));
    }
    m__io->seek(_pos);
    f_symbol_table = true;
    return m_symbol_table;
}

microsoft_pe_t::annoyingstring_t::annoyingstring_t(kaitai::kstream* p__io, microsoft_pe_t::coff_symbol_t* p__parent, microsoft_pe_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_name_from_offset = false;
    f_name_offset = false;
    f_name = false;
    f_name_zeroes = false;
    f_name_from_short = false;

    try {
        _read();
    } catch(...) {
        _clean_up();
        throw;
    }
}

void microsoft_pe_t::annoyingstring_t::_read() {
}

microsoft_pe_t::annoyingstring_t::~annoyingstring_t() {
    _clean_up();
}

void microsoft_pe_t::annoyingstring_t::_clean_up() {
    if (f_name_from_offset && !n_name_from_offset) {
    }
    if (f_name_offset) {
    }
    if (f_name_zeroes) {
    }
    if (f_name_from_short && !n_name_from_short) {
    }
}

std::string microsoft_pe_t::annoyingstring_t::name_from_offset() {
    if (f_name_from_offset)
        return m_name_from_offset;
    n_name_from_offset = true;
    if (name_zeroes() == 0) {
        n_name_from_offset = false;
        kaitai::kstream *io = _root()->_io();
        std::streampos _pos = io->pos();
        io->seek(((name_zeroes() == 0) ? ((_parent()->_parent()->symbol_name_table_offset() + name_offset())) : (0)));
        m_name_from_offset = kaitai::kstream::bytes_to_str(io->read_bytes_term(0, false, true, false), std::string("ascii"));
        io->seek(_pos);
        f_name_from_offset = true;
    }
    return m_name_from_offset;
}

uint32_t microsoft_pe_t::annoyingstring_t::name_offset() {
    if (f_name_offset)
        return m_name_offset;
    std::streampos _pos = m__io->pos();
    m__io->seek(4);
    m_name_offset = m__io->read_u4le();
    m__io->seek(_pos);
    f_name_offset = true;
    return m_name_offset;
}

std::string microsoft_pe_t::annoyingstring_t::name() {
    if (f_name)
        return m_name;
    m_name = ((name_zeroes() == 0) ? (name_from_offset()) : (name_from_short()));
    f_name = true;
    return m_name;
}

uint32_t microsoft_pe_t::annoyingstring_t::name_zeroes() {
    if (f_name_zeroes)
        return m_name_zeroes;
    std::streampos _pos = m__io->pos();
    m__io->seek(0);
    m_name_zeroes = m__io->read_u4le();
    m__io->seek(_pos);
    f_name_zeroes = true;
    return m_name_zeroes;
}

std::string microsoft_pe_t::annoyingstring_t::name_from_short() {
    if (f_name_from_short)
        return m_name_from_short;
    n_name_from_short = true;
    if (name_zeroes() != 0) {
        n_name_from_short = false;
        std::streampos _pos = m__io->pos();
        m__io->seek(0);
        m_name_from_short = kaitai::kstream::bytes_to_str(m__io->read_bytes_term(0, false, true, false), std::string("ascii"));
        m__io->seek(_pos);
        f_name_from_short = true;
    }
    return m_name_from_short;
}

microsoft_pe_t::pe_header_t* microsoft_pe_t::pe() {
    if (f_pe)
        return m_pe;
    std::streampos _pos = m__io->pos();
    m__io->seek(mz()->ofs_pe());
    m_pe = new pe_header_t(m__io, this, m__root);
    m__io->seek(_pos);
    f_pe = true;
    return m_pe;
}