Skip to content

Pe

Description

Parsed PE file. Holds the raw bytes plus decoded indices. All three PeOpen* constructors leave the parser as the sole owner of data – see the L / R semantics on the FromMemory / FromMemoryCopy constructors (mirrors VecInsertL / VecInsertR).

Fields

Name Description
allocator Allocator for data and the sections vector.
data Pointer to the raw PE bytes (owned).
data_size Length of data in bytes.
machine Decoded IMAGE_FILE_HEADER.Machine.
is_pe32_plus True for PE32+ (64-bit). v1 supports both PE32 and PE32+ headers, but the address-bearing fields are widened to 64 bits even on PE32.
image_base OptionalHeader.ImageBase – the runtime virtual address the loader places the image at when no relocation is required.
size_of_image OptionalHeader.SizeOfImage – total in-memory size (helps bounds-check RVAs).
sections All section headers, in original order.
codeview CodeView debug record, if present.

Usage example (Cross-references)

Usage examples (Cross-references)
    
    #include <Misra.h>
    #include <Misra/Parsers/Pe.h>
    #include <Misra/Std/Zstr.h>
    #include <Misra/Std/Allocator/Default.h>
        build_pe_blob();
    
        Pe pe;
        bool   ok = PeOpenFromMemoryCopy(&pe, blob, sizeof(blob), base);
        if (!ok) {
    
        build_pe_blob();
        Pe pe;
        if (!PeOpenFromMemoryCopy(&pe, blob, sizeof(blob), base)) {
            DefaultAllocatorDeinit(&alloc);
        garbage[1] = 'X';
    
        Pe pe;
        bool   ok = !PeOpenFromMemoryCopy(&pe, garbage, sizeof(garbage), base);
    
    int main(void) {
        WriteFmt("[INFO] Starting Pe tests\n\n");
    
        TestFunction tests[] = {
        };
    
        return run_test_suite(tests, sizeof(tests) / sizeof(tests[0]), NULL, 0, "Pe");
    }
    //
    // On success populates `out_path` (an owned Str the caller frees).
    static bool find_pdb(const Pe *pe, const char *pe_path, Str *out_path) {
        if (!pe->codeview.present || !pe->codeview.pdb_path)
            return false;
    
    #include <Misra/Std/Container/Buf.h>
    #include <Misra/Parsers/Pe.h>
    
    // ---------------------------------------------------------------------------
    
    typedef struct PeContext {
        Pe     *out;
        BufIter file;      // bounds for the whole image
        u32     nt_offset; // offset of NT signature
    // MemSets the caller's view. Anything that fails past the snapshot
    // cleans up via PeDeinit -- the buffer never leaks.
    bool pe_open_from_memory(Pe *out, Buf *in) {
        if (!out || !in || !in->data || !in->allocator) {
            LOG_FATAL("PeOpenFromMemory: NULL argument (contract violation)");
    
    // R-value form: allocate Buf, copy, hand `&copy` to the L-form.
    bool pe_open_from_memory_copy(Pe *out, const u8 *data, size data_size, Allocator *alloc) {
        if (!out || !data || !alloc) {
            LOG_FATAL("PeOpenFromMemoryCopy: NULL argument (contract violation)");
    }
    
    bool pe_open(Pe *out, const char *path, Allocator *alloc) {
        if (!out || !path || !alloc) {
            LOG_FATAL("PeOpen: NULL argument (contract violation)");
    }
    
    void PeDeinit(Pe *self) {
        if (!self)
            return;
    }
    
    const PeSection *PeFindSection(const Pe *self, const char *name) {
        if (!self || !name)
            return NULL;
    }
    
    bool PeRvaToOffset(const Pe *self, u32 rva, u64 *out_offset) {
        if (!self || !out_offset)
            return false;
    
    #include <Misra/Parsers/Pdb.h>
    #include <Misra/Parsers/Pe.h>
    #include <Misra/Std/Allocator.h>
    #include <Misra/Std/Container/Vec.h>
        char   *module_path; // owned copy
        u64     module_base; // last-seen runtime load base
        Pe  pe;
        Pdb pdb;
        bool    pe_open;
        PeSections     sections;
        PeCodeViewInfo codeview;
    } Pe;
    
    ///
    /// TAGS: Parser, PE, File
    ///
    bool pe_open(Pe *out, const char *path, Allocator *alloc);
    #define PeOpen(...) MISRA_OVERLOAD(PeOpen, __VA_ARGS__)
    #define PeOpen_2(out, path)                                                                                            \
    /// TAGS: Parser, PE, Memory, Ownership
    ///
    bool pe_open_from_memory(Pe *out, Buf *in);
    #define PeOpenFromMemory(out, in) pe_open_from_memory((out), (in))
    /// TAGS: Parser, PE, Memory, Copy
    ///
    bool pe_open_from_memory_copy(Pe *out, const u8 *data, size data_size, Allocator *alloc);
    #define PeOpenFromMemoryCopy(...)                    MISRA_OVERLOAD(PeOpenFromMemoryCopy, __VA_ARGS__)
    #define PeOpenFromMemoryCopy_3(out, data, data_size) pe_open_from_memory_copy((out), (data), (data_size), MisraScope)
    /// tears down the sections vector. Safe on a zeroed struct.
    ///
    void PeDeinit(Pe *self);
    
    ///
    /// they're vanishingly rare).
    ///
    const PeSection *PeFindSection(const Pe *self, const char *name);
    
    ///
    /// TAGS: Parser, PE, Address
    ///
    bool PeRvaToOffset(const Pe *self, u32 rva, u64 *out_offset);
    
    #endif // MISRA_PARSERS_PE_H
Last updated on