Skip to content

PeFile

Description

Parsed PE file. Holds the raw bytes plus decoded indices. Like ElfFile, supports both an owned-buffer and a borrowed-buffer construction path.

Fields

Name Description
allocator Allocator for the owned buffer (if any) and the sections vector.
data Pointer to the raw PE bytes.
data_size Length of data in bytes.
owns_data True if data was allocated via allocator.
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)
        build_pe_blob();
    
        PeFile pe;
        bool   ok = PeFileOpenFromMemory(&pe, blob, sizeof(blob), base);
        if (!ok) {
    
        build_pe_blob();
        PeFile pe;
        if (!PeFileOpenFromMemory(&pe, blob, sizeof(blob), base)) {
            DefaultAllocatorDeinit(&alloc);
        garbage[1] = 'X';
    
        PeFile pe;
        bool   ok = !PeFileOpenFromMemory(&pe, garbage, sizeof(garbage), base);
    //
    // On success populates `out_path` (an owned Str the caller frees).
    static bool find_pdb(const PeFile *pe, const char *pe_path, Str *out_path) {
        if (!pe->codeview.present || !pe->codeview.pdb_path)
            return false;
    
    typedef struct PeContext {
        PeFile    *out;
        ByteCursor file;      // bounds for the whole image
        u32        nt_offset; // offset of NT signature
    // ---------------------------------------------------------------------------
    
    bool PeFileOpenFromMemory(PeFile *out, u8 *data, size data_size, Allocator *alloc) {
        if (!out || !data || !alloc) {
            LOG_ERROR("PeFileOpenFromMemory: NULL argument");
    }
    
    bool PeFileOpen(PeFile *out, const char *path, Allocator *alloc) {
        if (!out || !path || !alloc) {
            LOG_ERROR("PeFileOpen: NULL argument");
    }
    
    void PeFileDeinit(PeFile *self) {
        if (!self)
            return;
    }
    
    const PeSection *PeFileFindSection(const PeFile *self, const char *name) {
        if (!self || !name)
            return NULL;
    }
    
    bool PeFileRvaToOffset(const PeFile *self, u32 rva, u64 *out_offset) {
        if (!self || !out_offset)
            return false;
        char   *module_path; // owned copy
        u64     module_base; // last-seen runtime load base
        PeFile  pe;
        PdbFile pdb;
        bool    pe_open;
        PeSections     sections;
        PeCodeViewInfo codeview;
    } PeFile;
    
    ///
    /// TAGS: Parser, PE, File
    ///
    bool PeFileOpen(PeFile *out, const char *path, Allocator *alloc);
    
    ///
    /// TAGS: Parser, PE, Memory
    ///
    bool PeFileOpenFromMemory(PeFile *out, u8 *data, size data_size, Allocator *alloc);
    
    ///
    /// `owns_data` was true. Safe on a zeroed struct.
    ///
    void PeFileDeinit(PeFile *self);
    
    ///
    /// they're vanishingly rare).
    ///
    const PeSection *PeFileFindSection(const PeFile *self, const char *name);
    
    ///
    /// TAGS: Parser, PE, Address
    ///
    bool PeFileRvaToOffset(const PeFile *self, u32 rva, u64 *out_offset);
    
    #endif // MISRA_PARSERS_PE_H
Last updated on