pass over PE

* upgraded PE with parsers for imports, exports, and tls
* added struct definitions for image load config and debug dir structs
This commit is contained in:
Nikita Smith
2024-12-06 11:53:16 -08:00
parent 80fa226432
commit 86db833a83
3 changed files with 1288 additions and 228 deletions
+467 -177
View File
@@ -56,22 +56,22 @@ enum
typedef U16 PE_ImageFileCharacteristics;
enum
{
PE_ImageFileCharacteristic_STRIPPED = (1 << 0),
PE_ImageFileCharacteristic_EXE = (1 << 1),
PE_ImageFileCharacteristic_NUMS_STRIPPED = (1 << 2),
PE_ImageFileCharacteristic_PE_STRIPPED = (1 << 3),
PE_ImageFileCharacteristic_AGGRESIVE_WS_TRIM = (1 << 4),
PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE = (1 << 5),
PE_ImageFileCharacteristic_UNUSED1 = (1 << 6),
PE_ImageFileCharacteristic_BYTES_RESERVED_LO = (1 << 7),
PE_ImageFileCharacteristic_32BIT_MACHINE = (1 << 8),
PE_ImageFileCharacteristic_DEBUG_STRIPPED = (1 << 9),
PE_ImageFileCharacteristic_FILE_REMOVABLE_RUN_FROM_SWAP = (1 << 10),
PE_ImageFileCharacteristic_NET_RUN_FROM_SWAP = (1 << 11),
PE_ImageFileCharacteristic_FILE_SYSTEM = (1 << 12),
PE_ImageFileCharacteristic_FILE_DLL = (1 << 13),
PE_ImageFileCharacteristic_FILE_UP_SYSTEM_ONLY = (1 << 14),
PE_ImageFileCharacteristic_BYTES_RESERVED_HI = (1 << 15),
PE_ImageFileCharacteristic_STRIPPED = (1 << 0),
PE_ImageFileCharacteristic_EXE = (1 << 1),
PE_ImageFileCharacteristic_NUMS_STRIPPED = (1 << 2),
PE_ImageFileCharacteristic_PE_STRIPPED = (1 << 3),
PE_ImageFileCharacteristic_AGGRESIVE_WS_TRIM = (1 << 4),
PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE = (1 << 5),
PE_ImageFileCharacteristic_UNUSED1 = (1 << 6),
PE_ImageFileCharacteristic_BYTES_RESERVED_LO = (1 << 7),
PE_ImageFileCharacteristic_32BIT_MACHINE = (1 << 8),
PE_ImageFileCharacteristic_DEBUG_STRIPPED = (1 << 9),
PE_ImageFileCharacteristic_FILE_REMOVABLE_RUN_FROM_SWAP = (1 << 10),
PE_ImageFileCharacteristic_NET_RUN_FROM_SWAP = (1 << 11),
PE_ImageFileCharacteristic_FILE_SYSTEM = (1 << 12),
PE_ImageFileCharacteristic_FILE_DLL = (1 << 13),
PE_ImageFileCharacteristic_FILE_UP_SYSTEM_ONLY = (1 << 14),
PE_ImageFileCharacteristic_BYTES_RESERVED_HI = (1 << 15),
};
typedef U16 PE_DllCharacteristics;
@@ -93,70 +93,70 @@ enum
typedef struct PE_OptionalHeader32 PE_OptionalHeader32;
struct PE_OptionalHeader32
{
U16 magic;
U8 major_linker_version;
U8 minor_linker_version;
U32 sizeof_code;
U32 sizeof_inited_data;
U32 sizeof_uninited_data;
U32 entry_point_va;
U32 code_base;
U32 data_base;
U32 image_base;
U32 section_alignment;
U32 file_alignment;
U16 major_os_ver;
U16 minor_os_ver;
U16 major_img_ver;
U16 minor_img_ver;
U16 major_subsystem_ver;
U16 minor_subsystem_ver;
U32 win32_version_value;
U32 sizeof_image;
U32 sizeof_headers;
U32 check_sum;
PE_WindowsSubsystem subsystem;
U16 magic;
U8 major_linker_version;
U8 minor_linker_version;
U32 sizeof_code;
U32 sizeof_inited_data;
U32 sizeof_uninited_data;
U32 entry_point_va;
U32 code_base;
U32 data_base;
U32 image_base;
U32 section_alignment;
U32 file_alignment;
U16 major_os_ver;
U16 minor_os_ver;
U16 major_img_ver;
U16 minor_img_ver;
U16 major_subsystem_ver;
U16 minor_subsystem_ver;
U32 win32_version_value;
U32 sizeof_image;
U32 sizeof_headers;
U32 check_sum;
PE_WindowsSubsystem subsystem;
PE_DllCharacteristics dll_characteristics;
U32 sizeof_stack_reserve;
U32 sizeof_stack_commit;
U32 sizeof_heap_reserve;
U32 sizeof_heap_commit;
U32 loader_flags;
U32 data_dir_count;
U32 sizeof_stack_reserve;
U32 sizeof_stack_commit;
U32 sizeof_heap_reserve;
U32 sizeof_heap_commit;
U32 loader_flags;
U32 data_dir_count;
};
typedef struct PE_OptionalHeader32Plus PE_OptionalHeader32Plus;
struct PE_OptionalHeader32Plus
{
U16 magic;
U8 major_linker_version;
U8 minor_linker_version;
U32 sizeof_code;
U32 sizeof_inited_data;
U32 sizeof_uninited_data;
U32 entry_point_va;
U32 code_base;
U64 image_base;
U32 section_alignment;
U32 file_alignment;
U16 major_os_ver;
U16 minor_os_ver;
U16 major_img_ver;
U16 minor_img_ver;
U16 major_subsystem_ver;
U16 minor_subsystem_ver;
U32 win32_version_value;
U32 sizeof_image;
U32 sizeof_headers;
U32 check_sum;
PE_WindowsSubsystem subsystem;
U16 magic;
U8 major_linker_version;
U8 minor_linker_version;
U32 sizeof_code;
U32 sizeof_inited_data;
U32 sizeof_uninited_data;
U32 entry_point_va;
U32 code_base;
U64 image_base;
U32 section_alignment;
U32 file_alignment;
U16 major_os_ver;
U16 minor_os_ver;
U16 major_img_ver;
U16 minor_img_ver;
U16 major_subsystem_ver;
U16 minor_subsystem_ver;
U32 win32_version_value;
U32 sizeof_image;
U32 sizeof_headers;
U32 check_sum;
PE_WindowsSubsystem subsystem;
PE_DllCharacteristics dll_characteristics;
U64 sizeof_stack_reserve;
U64 sizeof_stack_commit;
U64 sizeof_heap_reserve;
U64 sizeof_heap_commit;
U32 loader_flags;
U32 data_dir_count;
U64 sizeof_stack_reserve;
U64 sizeof_stack_commit;
U64 sizeof_heap_reserve;
U64 sizeof_heap_commit;
U32 loader_flags;
U32 data_dir_count;
};
typedef enum PE_DataDirectoryIndex
@@ -229,21 +229,32 @@ enum
PE_FPOEncoded_FLAGS_SHIFT = 11, PE_FPOEncoded_FLAGS_MASK = 0x7,
PE_FPOEncoded_FRAME_TYPE_SHIFT = 14, PE_FPOEncoded_FRAME_TYPE_MASK = 0x3,
};
#define PE_FPOEncoded_Extract_PROLOG_SIZE(f) (U8)(((f) >> PE_FPOEncoded_PROLOG_SIZE_SHIFT) & PE_FPOEncoded_PROLOG_SIZE_MASK)
#define PE_FPOEncoded_Extract_PROLOG_SIZE(f) (U8)(((f) >> PE_FPOEncoded_PROLOG_SIZE_SHIFT) & PE_FPOEncoded_PROLOG_SIZE_MASK)
#define PE_FPOEncoded_Extract_SAVED_REGS_SIZE(f) (U8)(((f) >> PE_FPOEncoded_SAVED_REGS_SIZE_SHIFT) & PE_FPOEncoded_SAVED_REGS_SIZE_MASK)
#define PE_FPOEncoded_Extract_FLAGS(f) (U8)(((f) >> PE_FPOEncoded_FLAGS_SHIFT) & PE_FPOEncoded_FLAGS_MASK)
#define PE_FPOEncoded_Extract_FRAME_TYPE(f) (U8)(((f) >> PE_FPOEncoded_FRAME_TYPE_SHIFT) & PE_FPOEncoded_FRAME_TYPE_MASK)
#define PE_FPOEncoded_Extract_FLAGS(f) (U8)(((f) >> PE_FPOEncoded_FLAGS_SHIFT) & PE_FPOEncoded_FLAGS_MASK)
#define PE_FPOEncoded_Extract_FRAME_TYPE(f) (U8)(((f) >> PE_FPOEncoded_FRAME_TYPE_SHIFT) & PE_FPOEncoded_FRAME_TYPE_MASK)
typedef U8 PE_FPOType;
enum
{
PE_FPOType_FPO = 0,
PE_FPOType_TRAP = 1,
PE_FPOType_TSS = 2,
PE_FPOType_FPO = 0,
PE_FPOType_TRAP = 1,
PE_FPOType_TSS = 2,
PE_FPOType_NOFPO = 3,
PE_FPOType_COUNT = 4
};
// winnt.h: FPO_DATA
typedef struct PE_DebugFPO PE_DebugFPO;
struct PE_DebugFPO
{
U32 func_code_off;
U32 func_size;
U32 locals_size;
U16 params_size;
U16 flags;
};
typedef U32 PE_DebugMiscType;
enum
{
@@ -252,17 +263,42 @@ enum
PE_DebugMiscType_COUNT = 2
};
// winnt.h: IMAGE_DEBUG_MISC
typedef struct PE_DebugMisc PE_DebugMisc;
struct PE_DebugMisc
{
PE_DebugMiscType data_type;
U32 size;
U8 unicode;
U8 pad[3];
//char name[];
};
// winnt.h: IMAGE_COFF_SYMBOLS_HEADER
typedef struct PE_DebugCoff PE_DebugCoff;
struct PE_DebugCoff
{
U32 symbol_count;
U32 lva_to_first_symbol;
U32 line_number_count;
U32 lva_to_first_line_number;
U32 virt_off_to_first_byte_of_code;
U32 virt_off_to_last_byte_of_code;
U32 virt_off_to_first_byte_of_data;
U32 virt_off_to_last_byte_of_data;
};
typedef struct PE_DebugDirectory PE_DebugDirectory;
struct PE_DebugDirectory
{
U32 characteristics;
COFF_TimeStamp time_stamp;
U16 major_ver;
U16 minor_ver;
U32 characteristics;
COFF_TimeStamp time_stamp;
U16 major_ver;
U16 minor_ver;
PE_DebugDirectoryType type;
U32 size;
U32 voff;
U32 foff;
U32 size;
U32 voff;
U32 foff;
};
typedef U32 PE_GlobalFlags;
@@ -318,6 +354,133 @@ enum
};
#define PE_LoadConfigGuardFlags_Extract_CF_FUNCTION_TABLE_SIZE(f) (U32)(((f) >> PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_SHIFT) & PE_LoadConfigGuardFlags_CF_FUNCTION_TABLE_SIZE_MASK)
typedef struct PE_LoadConfigCodeIntegrity PE_LoadConfigCodeIntegrity;
struct PE_LoadConfigCodeIntegrity
{
U16 flags;
U16 catalog;
U32 catalog_offset;
U32 reserved;
};
typedef struct PE_LoadConfig32 PE_LoadConfig32;
struct PE_LoadConfig32
{
U32 size;
COFF_TimeStamp time_stamp;
U16 major_version;
U16 minor_version;
U32 global_flag_clear;
U32 global_flag_set;
U32 critical_section_timeout;
U32 decommit_free_block_threshold;
U32 decommit_total_free_threshold;
U32 lock_prefix_table;
U32 maximum_allocation_size;
U32 virtual_memory_threshold;
U32 process_affinity_mask;
U32 process_heap_flags;
U16 csd_version;
U16 reserved;
U32 edit_list;
U32 security_cookie;
U32 seh_handler_table;
U32 seh_handler_count;
// msvc 2015
U32 guard_cf_check_func_ptr;
U32 guard_cf_dispatch_func_ptr;
U32 guard_cf_func_table;
U32 guard_cf_func_count;
U32 guard_flags;
// msvc 2017
PE_LoadConfigCodeIntegrity code_integrity;
U32 guard_address_taken_iat_entry_table;
U32 guard_address_taken_iat_entry_count;
U32 guard_long_jump_target_table;
U32 guard_long_jump_target_count;
U32 dynamic_value_reloc_table;
U32 chpe_metadata_ptr;
U32 guard_rf_failure_routine;
U32 guard_rf_failure_routine_func_ptr;
U32 dynamic_value_reloc_table_offset;
U16 dynamic_value_reloc_table_section;
U16 reserved2;
U32 guard_rf_verify_stack_pointer_func_ptr;
U32 hot_patch_table_offset;
// msvc 2019
U32 reserved3;
U32 enclave_config_ptr;
U32 volatile_metadata_ptr;
U32 guard_eh_continue_table;
U32 guard_eh_continue_count;
U32 guard_xfg_check_func_ptr;
U32 guard_xfg_dispatch_func_ptr;
U32 guard_xfg_table_dispatch_func_ptr;
U32 cast_guard_os_determined_failure_mode;
};
typedef struct PE_LoadConfig64 PE_LoadConfig64;
struct PE_LoadConfig64
{
U32 size;
COFF_TimeStamp time_stamp;
U16 major_version;
U16 minor_version;
U32 global_flag_clear;
U32 global_flag_set;
U32 critical_section_timeout;
U64 decommit_free_block_threshold;
U64 decommit_total_free_threshold;
U64 lock_prefix_table;
U64 maximum_allocation_size;
U64 virtual_memory_threshold;
U64 process_affinity_mask;
U32 process_heap_flags;
U16 csd_version;
U16 reserved;
U64 edit_list;
U64 security_cookie;
U64 seh_handler_table;
U64 seh_handler_count;
// msvc 2015
U64 guard_cf_check_func_ptr;
U64 guard_cf_dispatch_func_ptr;
U64 guard_cf_func_table;
U64 guard_cf_func_count;
U32 guard_flags;
// msvc 2017
PE_LoadConfigCodeIntegrity code_integrity;
U64 guard_address_taken_iat_entry_table;
U64 guard_address_taken_iat_entry_count;
U64 guard_long_jump_target_table;
U64 guard_long_jump_target_count;
U64 dynamic_value_reloc_table;
U64 chpe_metadata_ptr;
U64 guard_rf_failure_routine;
U64 guard_rf_failure_routine_func_ptr;
U32 dynamic_value_reloc_table_offset;
U16 dynamic_value_reloc_table_section;
U16 reserved2;
U64 guard_rf_verify_stack_pointer_func_ptr;
U32 hot_patch_table_offset;
// msvc 2019
U32 reserved3;
U64 enclave_config_ptr;
U64 volatile_metadata_ptr;
U64 guard_eh_continue_table;
U64 guard_eh_continue_count;
U64 guard_xfg_check_func_ptr;
U64 guard_xfg_dispatch_func_ptr;
U64 guard_xfg_table_dispatch_func_ptr;
U64 cast_guard_os_determined_failure_mode;
};
// this is the "MZ" as a 16-bit short
#define PE_DOS_MAGIC 0x5a4d
#define PE_MAGIC 0x00004550u
@@ -362,10 +525,10 @@ struct PE_IntelPdata
typedef struct PE_CvHeaderPDB20 PE_CvHeaderPDB20;
struct PE_CvHeaderPDB20
{
U32 magic;
U32 offset;
U32 time;
U32 age;
U32 magic;
U32 offset;
COFF_TimeStamp time_stamp;
U32 age;
// file name packed after struct
};
@@ -389,11 +552,11 @@ struct PE_CvHeaderRDI
typedef struct PE_ImportEntry PE_ImportEntry;
struct PE_ImportEntry
{
U32 lookup_table_voff;
U32 lookup_table_voff;
COFF_TimeStamp time_stamp;
U32 forwarder_chain;
U32 name_voff;
U32 import_addr_table_voff;
U32 forwarder_chain;
U32 name_voff;
U32 import_addr_table_voff;
};
typedef struct PE_DelayedImportEntry PE_DelayedImportEntry;
@@ -401,55 +564,55 @@ struct PE_DelayedImportEntry
{
// According to COFF/PE spec this field is unused and should be set zero,
// but when I compile mule with MSVC 2019 this is set to 1.
U32 attributes;
U32 name_voff; // Name of the DLL
U32 module_handle_voff; // Place where module handle from LoadLibrary is stored
U32 iat_voff;
U32 name_table_voff; // Array of hint/name or oridnals
U32 bound_table_voff; // (Optional) Points to an array of PE_ThunkData
U32 unload_table_voff; // (Optional) Copy of iat_voff
U32 attributes;
U32 name_voff; // Name of the DLL
U32 module_handle_voff; // Place where module handle from LoadLibrary is stored
U32 iat_voff;
U32 name_table_voff; // Array of hint/name or oridnals
U32 bound_table_voff; // (Optional) Points to an array of PE_ThunkData
U32 unload_table_voff; // (Optional) Copy of iat_voff
// 0 not bound
// -1 if bound and real timestamp located in bounded import directory
// Otherwise time when dll was bound
COFF_TimeStamp time_stamp;
COFF_TimeStamp time_stamp;
};
typedef struct PE_ExportTable PE_ExportTable;
struct PE_ExportTable
typedef struct PE_ExportTableHeader PE_ExportTableHeader;
struct PE_ExportTableHeader
{
U32 flags; // must be zero
COFF_TimeStamp time_stamp; // time and date when export table was created
U16 major_ver; // table version, user can change major and minor version
U16 minor_ver;
U32 name_voff; // ASCII name of the dll
U32 ordinal_base; // Starting oridnal number
U32 export_address_table_count;
U32 name_pointer_table_count;
U32 export_address_table_voff;
U32 name_pointer_table_voff;
U32 ordinal_table_voff;
U32 flags; // must be zero
COFF_TimeStamp time_stamp; // time and date when export table was created
U16 major_ver; // table version, user can change major and minor version
U16 minor_ver;
U32 name_voff; // ASCII name of the dll
U32 ordinal_base; // Starting oridnal number
U32 export_address_table_count;
U32 name_pointer_table_count;
U32 export_address_table_voff;
U32 name_pointer_table_voff;
U32 ordinal_table_voff;
};
typedef struct PE_TLSHeader32 PE_TLSHeader32;
struct PE_TLSHeader32
{
U32 raw_data_start; // Range of initialized data that is copied for each thread from the image.
U32 raw_data_end; // (Typically points to .tls section)
U32 index_address; // Address where image loader places TLS slot index.
U32 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors.
U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS.
U32 characteristics; // COFF_SectionFlags but only align flags are used.
U32 raw_data_start; // Range of initialized data that is copied for each thread from the image.
U32 raw_data_end; // (Typically points to .tls section)
U32 index_address; // Address where image loader places TLS slot index.
U32 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors.
U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS.
COFF_SectionFlags characteristics; // COFF_SectionFlags but only align flags are used.
};
typedef struct PE_TLSHeader64 PE_TLSHeader64;
struct PE_TLSHeader64
{
U64 raw_data_start; // Range of initialized data that is copied for each thread from the image.
U64 raw_data_end; // (Typically points to .tls section)
U64 index_address; // Address where image loader places TLS slot index.
U64 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors.
U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS.
U32 characteristics; // COFF_SectionFlags but only align flags are used.
U64 raw_data_start; // Range of initialized data that is copied for each thread from the image.
U64 raw_data_end; // (Typically points to .tls section)
U64 index_address; // Address where image loader places TLS slot index.
U64 callbacks_address; // Zero terminated list of callbacks used for initializing data with constructors.
U32 zero_fill_size; // Amount of memory to fill with zeroes in TLS.
COFF_SectionFlags characteristics; // COFF_SectionFlags but only align flags are used.
};
global read_only U8 PE_RES_MAGIC[] =
@@ -506,15 +669,15 @@ typedef struct PE_ResourceHeader PE_ResourceHeader;
struct PE_ResourceHeader
{
COFF_ResourceHeaderPrefix prefix;
U16 type;
U16 pad0;
U16 name;
U16 pad1;
U32 data_version;
COFF_ResourceMemoryFlags memory_flags;
U16 language_id;
U32 version;
U32 characteristics;
U16 type;
U16 pad0;
U16 name;
U16 pad1;
U32 data_version;
COFF_ResourceMemoryFlags memory_flags;
U16 language_id;
U32 version;
U32 characteristics;
};
typedef U16 PE_BaseRelocKind;
@@ -605,6 +768,7 @@ union PE_UnwindCode
#define PE_UNWIND_INFO_FLAGS_FROM_HDR(x) (((x) >> 3)&0x1F)
#define PE_UNWIND_INFO_REG_FROM_FRAME(x) ((x)&0xF)
#define PE_UNWIND_INFO_OFF_FROM_FRAME(x) (((x) >> 4)&0xF)
#define PE_UNWIND_INFO_GET_CODE_COUNT(x) (((x)+1) & ~1)
typedef struct PE_UnwindInfo PE_UnwindInfo;
struct PE_UnwindInfo
@@ -638,8 +802,8 @@ read_only global String8 pe_dos_program = {pe_dos_program_data, sizeof(pe_dos_pr
typedef struct PE_BaseRelocBlock PE_BaseRelocBlock;
struct PE_BaseRelocBlock
{
U64 page_virt_off;
U64 entry_count;
U64 page_virt_off;
U64 entry_count;
U16 *entries;
};
@@ -647,7 +811,7 @@ typedef struct PE_BaseRelocBlockNode PE_BaseRelocBlockNode;
struct PE_BaseRelocBlockNode
{
PE_BaseRelocBlockNode *next;
PE_BaseRelocBlock v;
PE_BaseRelocBlock v;
};
typedef struct PE_BaseRelocBlockList PE_BaseRelocBlockList;
@@ -655,7 +819,7 @@ struct PE_BaseRelocBlockList
{
PE_BaseRelocBlockNode *first;
PE_BaseRelocBlockNode *last;
U64 count;
U64 count;
};
//- rjf: resources
@@ -664,29 +828,27 @@ typedef struct PE_Resource PE_Resource;
struct PE_Resource
{
COFF_ResourceID id;
PE_ResDataKind kind;
PE_ResDataKind kind;
union
{
COFF_ResourceDataEntry leaf;
struct PE_ResourceDir *dir;
struct
{
COFF_ResourceID type;
U32 data_version;
U32 version;
COFF_ResourceID type;
U32 data_version;
U32 version;
COFF_ResourceMemoryFlags memory_flags;
String8 data;
}
coff_res;
}
u;
String8 data;
} coff_res;
} u;
};
typedef struct PE_ResourceNode PE_ResourceNode;
struct PE_ResourceNode
{
PE_ResourceNode *next;
PE_Resource data;
PE_Resource data;
};
typedef struct PE_ResourceList PE_ResourceList;
@@ -694,69 +856,197 @@ struct PE_ResourceList
{
PE_ResourceNode *first;
PE_ResourceNode *last;
U64 count;
U64 count;
};
typedef struct PE_ResourceArray PE_ResourceArray;
struct PE_ResourceArray
{
PE_Resource *v;
U64 count;
U64 count;
};
typedef struct PE_ResourceDir PE_ResourceDir;
struct PE_ResourceDir
{
U32 characteristics;
COFF_TimeStamp time_stamp;
U16 major_version;
U16 minor_version;
U32 characteristics;
COFF_TimeStamp time_stamp;
U16 major_version;
U16 minor_version;
PE_ResourceList named_list;
PE_ResourceList id_list;
};
//- exports & imports
typedef struct PE_ParsedExport PE_ParsedExport;
struct PE_ParsedExport
{
String8 forwarder;
String8 name;
U64 voff;
U64 ordinal;
};
typedef struct PE_ParsedExportTable PE_ParsedExportTable;
struct PE_ParsedExportTable
{
U32 flags;
COFF_TimeStamp time_stamp;
U16 major_ver;
U16 minor_ver;
U64 ordinal_base;
U64 export_count;
PE_ParsedExport *exports;
};
typedef U32 PE_ParsedImportType;
enum PE_ParsedImportTypeEnum
{
PE_ParsedImport_Null,
PE_ParsedImport_Ordinal,
PE_ParsedImport_Name,
};
typedef struct PE_ParsedImport PE_ParsedImport;
struct PE_ParsedImport
{
PE_ParsedImportType type;
union
{
U16 ordinal;
struct
{
U64 hint;
String8 string;
} name;
} u;
};
typedef struct PE_ParsedStaticDLLImport PE_ParsedStaticDLLImport;
struct PE_ParsedStaticDLLImport
{
String8 name;
U64 import_address_table_voff;
U64 import_name_table_voff;
COFF_TimeStamp time_stamp;
U64 forwarder_chain;
U64 import_count;
PE_ParsedImport *imports;
};
typedef struct PE_ParsedStaticImportTable PE_ParsedStaticImportTable;
struct PE_ParsedStaticImportTable
{
U64 count;
PE_ParsedStaticDLLImport *v;
};
typedef struct PE_ParsedDelayDLLImport PE_ParsedDelayDLLImport;
struct PE_ParsedDelayDLLImport
{
U32 attributes;
String8 name;
U64 module_handle_voff;
U64 iat_voff;
U64 name_table_voff;
U64 bound_table_voff;
U64 unload_table_voff;
COFF_TimeStamp time_stamp;
U64 bound_table_count;
U64 *bound_table;
U64 unload_table_count;
U64 *unload_table;
U64 import_count;
PE_ParsedImport *imports;
};
typedef struct PE_ParsedDelayImportTable PE_ParsedDelayImportTable;
struct PE_ParsedDelayImportTable
{
U64 count;
PE_ParsedDelayDLLImport *v;
};
typedef struct PE_ParsedTLS PE_ParsedTLS;
struct PE_ParsedTLS
{
PE_TLSHeader64 header;
U64 callback_count;
U64 *callback_addrs;
};
////////////////////////////////
// SEH Scope Table
typedef struct PE_HandlerScope PE_HandlerScope;
struct PE_HandlerScope
{
U32 begin;
U32 end;
U32 handler;
U32 target;
};
//- rjf: bundle
typedef struct PE_BinInfo PE_BinInfo;
struct PE_BinInfo
{
U64 image_base;
U64 entry_point;
B32 is_pe32;
U64 virt_section_align;
U64 file_section_align;
U64 section_array_off;
U64 section_count;
U64 symbol_array_off;
U64 symbol_count;
U64 string_table_off;
U64 dbg_path_off;
U64 dbg_path_size;
Guid dbg_guid;
U32 dbg_age;
U32 dbg_time;
Arch arch;
Rng1U64 *data_dir_franges;
U32 data_dir_count;
PE_TLSHeader64 tls_header;
U64 image_base;
U64 entry_point;
B32 is_pe32;
U64 virt_section_align;
U64 file_section_align;
U64 section_array_off;
U64 section_count;
U64 symbol_array_off;
U64 symbol_count;
U64 string_table_off;
U64 dbg_path_off;
U64 dbg_path_size;
Guid dbg_guid;
U32 dbg_age;
U32 dbg_time;
Arch arch;
Rng1U64 *data_dir_franges;
U32 data_dir_count;
PE_TLSHeader64 tls_header;
};
////////////////////////////////
//~ rjf: Basic Enum Functions
internal U32 pe_slot_count_from_unwind_op_code(PE_UnwindOpCode opcode);
internal String8 pe_string_from_subsystem(PE_WindowsSubsystem subsystem);
internal PE_WindowsSubsystem pe_subsystem_from_string(String8 string);
internal String8 pe_string_from_subsystem(PE_WindowsSubsystem x);
internal String8 pe_string_from_unwind_gpr_x64(PE_UnwindGprRegX64 x);
internal String8 pe_string_from_data_directory_index(PE_DebugDirectoryType x);
internal String8 pe_string_from_debug_directory_type(PE_DebugDirectoryType x);
internal String8 pe_string_from_fpo_type(PE_FPOType x);
internal String8 pe_string_from_misc_type(PE_DebugMiscType x);
internal String8 pe_resource_kind_to_string(PE_ResourceKind x);
internal String8 pe_string_from_fpo_flags(Arena *arena, PE_FPOFlags flags);
internal String8 pe_string_from_global_flags(Arena *arena, PE_GlobalFlags flags);
internal String8 pe_string_from_load_config_guard_flags(Arena *arena, PE_LoadConfigGuardFlags flags);
internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacteristics dll_chars);
////////////////////////////////
//~ rjf: Parser Functions
internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data);
internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range);
internal PE_ParsedTLS pe_tls_from_data(Arena *arena, COFF_MachineType machine, U64 image_base, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 tls_frange);
////////////////////////////////
//~ rjf: Helpers
internal U64 pe_intel_pdata_off_from_voff__binary_search(String8 data, PE_BinInfo *bin, U64 voff);
internal U64 pe_pdata_off_from_voff__binary_search_x8664(String8 raw_data, U64 voff);
internal void * pe_ptr_from_voff(String8 data, PE_BinInfo *bin, U64 voff);
internal U64 pe_section_num_from_voff(String8 data, PE_BinInfo *bin, U64 voff);
internal void * pe_ptr_from_section_num(String8 data, PE_BinInfo *bin, U64 n);