// Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_H #define COFF_H typedef U32 COFF_TimeStamp; //////////////////////////////// //~ rjf: Coff Format Types #pragma pack(push,1) typedef struct COFF_Guid COFF_Guid; struct COFF_Guid { U32 data1; U16 data2; U16 data3; U32 data4; U32 data5; }; typedef U16 COFF_Flags; enum { COFF_Flag_RELOC_STRIPPED = (1 << 0), COFF_Flag_EXECUTABLE_IMAGE = (1 << 1), COFF_Flag_LINE_NUMS_STRIPPED = (1 << 2), COFF_Flag_SYM_STRIPPED = (1 << 3), COFF_Flag_RESERVED_0 = (1 << 4), COFF_Flag_LARGE_ADDRESS_AWARE = (1 << 5), COFF_Flag_RESERVED_1 = (1 << 6), COFF_Flag_RESERVED_2 = (1 << 7), COFF_Flag_32BIT_MACHINE = (1 << 8), COFF_Flag_DEBUG_STRIPPED = (1 << 9), COFF_Flag_REMOVABLE_RUN_FROM_SWAP = (1 << 10), COFF_Flag_NET_RUN_FROM_SWAP = (1 << 11), COFF_Flag_SYSTEM = (1 << 12), COFF_Flag_DLL = (1 << 13), COFF_Flag_UP_SYSTEM_ONLY = (1 << 14), COFF_Flag_BYTES_RESERVED_HI = (1 << 15), }; typedef U16 COFF_MachineType; enum { COFF_MachineType_UNKNOWN = 0x0, COFF_MachineType_X86 = 0x14c, COFF_MachineType_X64 = 0x8664, COFF_MachineType_ARM33 = 0x1d3, COFF_MachineType_ARM = 0x1c0, COFF_MachineType_ARM64 = 0xaa64, COFF_MachineType_ARMNT = 0x1c4, COFF_MachineType_EBC = 0xebc, COFF_MachineType_IA64 = 0x200, COFF_MachineType_M32R = 0x9041, COFF_MachineType_MIPS16 = 0x266, COFF_MachineType_MIPSFPU = 0x366, COFF_MachineType_MIPSFPU16 = 0x466, COFF_MachineType_POWERPC = 0x1f0, COFF_MachineType_POWERPCFP = 0x1f1, COFF_MachineType_R4000 = 0x166, COFF_MachineType_RISCV32 = 0x5032, COFF_MachineType_RISCV64 = 0x5064, COFF_MachineType_RISCV128 = 0x5128, COFF_MachineType_SH3 = 0x1a2, COFF_MachineType_SH3DSP = 0x1a3, COFF_MachineType_SH4 = 0x1a6, COFF_MachineType_SH5 = 0x1a8, COFF_MachineType_THUMB = 0x1c2, COFF_MachineType_WCEMIPSV2 = 0x169, COFF_MachineType_COUNT = 25 }; typedef struct COFF_Header COFF_Header; struct COFF_Header { COFF_MachineType machine; U16 section_count; COFF_TimeStamp time_stamp; U32 symbol_table_foff; U32 symbol_count; U16 optional_header_size; COFF_Flags flags; }; typedef U32 COFF_SectionAlign; enum { COFF_SectionAlign_1BYTES = 0x1, COFF_SectionAlign_2BYTES = 0x2, COFF_SectionAlign_4BYTES = 0x3, COFF_SectionAlign_8BYTES = 0x4, COFF_SectionAlign_16BYTES = 0x5, COFF_SectionAlign_32BYTES = 0x6, COFF_SectionAlign_64BYTES = 0x7, COFF_SectionAlign_128BYTES = 0x8, COFF_SectionAlign_256BYTES = 0x9, COFF_SectionAlign_512BYTES = 0xA, COFF_SectionAlign_1024BYTES = 0xB, COFF_SectionAlign_2048BYTES = 0xC, COFF_SectionAlign_4096BYTES = 0xD, COFF_SectionAlign_8192BYTES = 0xE, COFF_SectionAlign_COUNT = 14 }; typedef U32 COFF_SectionFlags; enum { COFF_SectionFlag_TYPE_NO_PAD = (1 << 3), COFF_SectionFlag_CNT_CODE = (1 << 5), COFF_SectionFlag_CNT_INITIALIZED_DATA = (1 << 6), COFF_SectionFlag_CNT_UNINITIALIZED_DATA = (1 << 7), COFF_SectionFlag_LNK_OTHER = (1 << 8), COFF_SectionFlag_LNK_INFO = (1 << 9), COFF_SectionFlag_LNK_REMOVE = (1 << 11), COFF_SectionFlag_LNK_COMDAT = (1 << 12), COFF_SectionFlag_GPREL = (1 << 15), COFF_SectionFlag_MEM_16BIT = (1 << 17), COFF_SectionFlag_MEM_LOCKED = (1 << 18), COFF_SectionFlag_MEM_PRELOAD = (1 << 19), COFF_SectionFlag_ALIGN_SHIFT = 20, COFF_SectionFlag_ALIGN_MASK = 0xf, COFF_SectionFlag_LNK_NRELOC_OVFL = (1 << 24), COFF_SectionFlag_MEM_DISCARDABLE = (1 << 25), COFF_SectionFlag_MEM_NOT_CACHED = (1 << 26), COFF_SectionFlag_MEM_NOT_PAGED = (1 << 27), COFF_SectionFlag_MEM_SHARED = (1 << 28), COFF_SectionFlag_MEM_EXECUTE = (1 << 29), COFF_SectionFlag_MEM_READ = (1 << 30), COFF_SectionFlag_MEM_WRITE = (1 << 31), }; #define COFF_SectionFlags_Extract_ALIGN(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_ALIGN_SHIFT) & COFF_SectionFlag_ALIGN_MASK) #define COFF_SectionFlags_LNK_FLAGS ((COFF_SectionFlag_ALIGN_MASK << COFF_SectionFlag_ALIGN_SHIFT) | COFF_SectionFlag_LNK_COMDAT | COFF_SectionFlag_LNK_INFO | COFF_SectionFlag_LNK_OTHER | COFF_SectionFlag_LNK_REMOVE | COFF_SectionFlag_LNK_NRELOC_OVFL) typedef struct COFF_SectionHeader COFF_SectionHeader; struct COFF_SectionHeader { U8 name[8]; U32 vsize; U32 voff; U32 fsize; U32 foff; U32 relocs_foff; U32 lines_foff; U16 reloc_count; U16 line_count; COFF_SectionFlags flags; }; typedef U16 COFF_RelocTypeX64; enum { COFF_RelocTypeX64_ABS = 0x0, COFF_RelocTypeX64_ADDR64 = 0x1, COFF_RelocTypeX64_ADDR32 = 0x2, COFF_RelocTypeX64_ADDR32NB = 0x3, // NB => No Base COFF_RelocTypeX64_REL32 = 0x4, COFF_RelocTypeX64_REL32_1 = 0x5, COFF_RelocTypeX64_REL32_2 = 0x6, COFF_RelocTypeX64_REL32_3 = 0x7, COFF_RelocTypeX64_REL32_4 = 0x8, COFF_RelocTypeX64_REL32_5 = 0x9, COFF_RelocTypeX64_SECTION = 0xA, COFF_RelocTypeX64_SECREL = 0xB, COFF_RelocTypeX64_SECREL7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token COFF_RelocTypeX64_TOKEN = 0xD, COFF_RelocTypeX64_SREL32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR COFF_RelocTypeX64_PAIR = 0xF, COFF_RelocTypeX64_SSPAN32 = 0x10, COFF_RelocTypeX64_COUNT = 17 }; typedef U16 COFF_RelocTypeX86; enum { COFF_RelocTypeX86_ABS = 0x0, // relocation is ignored COFF_RelocTypeX86_DIR16 = 0x1, // no support COFF_RelocTypeX86_REL16 = 0x2, // no support COFF_RelocTypeX86_UNKNOWN0 = 0x3, COFF_RelocTypeX86_UNKNOWN2 = 0x4, COFF_RelocTypeX86_UNKNOWN3 = 0x5, COFF_RelocTypeX86_DIR32 = 0x6, // 32-bit virtual address COFF_RelocTypeX86_DIR32NB = 0x7, // 32-bit virtual offset COFF_RelocTypeX86_SEG12 = 0x9, // no support COFF_RelocTypeX86_SECTION = 0xA, // 16-bit section index, used for debug info purposes COFF_RelocTypeX86_SECREL = 0xB, // 32-bit offset from start of a section COFF_RelocTypeX86_TOKEN = 0xC, // CLR token? (for managed languages) COFF_RelocTypeX86_SECREL7 = 0xD, // 7-bit offset from the base of the section that contains the target. COFF_RelocTypeX86_UNKNOWN4 = 0xE, COFF_RelocTypeX86_UNKNOWN5 = 0xF, COFF_RelocTypeX86_UNKNOWN6 = 0x10, COFF_RelocTypeX86_UNKNOWN7 = 0x11, COFF_RelocTypeX86_UNKNOWN8 = 0x12, COFF_RelocTypeX86_UNKNOWN9 = 0x13, COFF_RelocTypeX86_REL32 = 0x14, COFF_RelocTypeX86_COUNT = 20 }; typedef U16 COFF_RelocTypeARM; enum { COFF_RelocTypeARM_ABS = 0x0, COFF_RelocTypeARM_ADDR32 = 0x1, COFF_RelocTypeARM_ADDR32NB = 0x2, COFF_RelocTypeARM_BRANCH24 = 0x3, COFF_RelocTypeARM_BRANCH11 = 0x4, COFF_RelocTypeARM_UNKNOWN1 = 0x5, COFF_RelocTypeARM_UNKNOWN2 = 0x6, COFF_RelocTypeARM_UNKNOWN3 = 0x7, COFF_RelocTypeARM_UNKNOWN4 = 0x8, COFF_RelocTypeARM_UNKNOWN5 = 0x9, COFF_RelocTypeARM_REL32 = 0xA, COFF_RelocTypeARM_SECTION = 0xE, COFF_RelocTypeARM_SECREL = 0xF, COFF_RelocTypeARM_MOV32 = 0x10, COFF_RelocTypeARM_THUMB_MOV32 = 0x11, COFF_RelocTypeARM_THUMB_BRANCH20 = 0x12, COFF_RelocTypeARM_UNUSED = 0x13, COFF_RelocTypeARM_THUMB_BRANCH24 = 0x14, COFF_RelocTypeARM_THUMB_BLX23 = 0x15, COFF_RelocTypeARM_PAIR = 0x16, COFF_RelocTypeARM_COUNT = 20 }; typedef U16 COFF_RelocTypeARM64; enum { COFF_RelocTypeARM64_ABS = 0x0, COFF_RelocTypeARM64_ADDR32 = 0x1, COFF_RelocTypeARM64_ADDR32NB = 0x2, COFF_RelocTypeARM64_BRANCH26 = 0x3, COFF_RelocTypeARM64_PAGEBASE_REL21 = 0x4, COFF_RelocTypeARM64_REL21 = 0x5, COFF_RelocTypeARM64_PAGEOFFSET_12A = 0x6, COFF_RelocTypeARM64_SECREL = 0x8, COFF_RelocTypeARM64_SECREL_LOW12A = 0x9, COFF_RelocTypeARM64_SECREL_HIGH12A = 0xA, COFF_RelocTypeARM64_SECREL_LOW12L = 0xB, COFF_RelocTypeARM64_TOKEN = 0xC, COFF_RelocTypeARM64_SECTION = 0xD, COFF_RelocTypeARM64_ADDR64 = 0xE, COFF_RelocTypeARM64_BRANCH19 = 0xF, COFF_RelocTypeARM64_BRANCH14 = 0x10, COFF_RelocTypeARM64_REL32 = 0x11, COFF_RelocTypeARM64_COUNT = 17 }; typedef U8 COFF_SymType; enum { COFF_SymType_NULL, COFF_SymType_VOID, COFF_SymType_CHAR, COFF_SymType_SHORT, COFF_SymType_INT, COFF_SymType_LONG, COFF_SymType_FLOAT, COFF_SymType_DOUBLE, COFF_SymType_STRUCT, COFF_SymType_UNION, COFF_SymType_ENUM, COFF_SymType_MOE, // member of enumeration COFF_SymType_BYTE, COFF_SymType_WORD, COFF_SymType_UINT, COFF_SymType_DWORD, COFF_SymType_COUNT = 16 }; typedef U8 COFF_SymStorageClass; enum { COFF_SymStorageClass_END_OF_FUNCTION = 0xff, COFF_SymStorageClass_NULL = 0, COFF_SymStorageClass_AUTOMATIC = 1, COFF_SymStorageClass_EXTERNAL = 2, COFF_SymStorageClass_STATIC = 3, COFF_SymStorageClass_REGISTER = 4, COFF_SymStorageClass_EXTERNAL_DEF = 5, COFF_SymStorageClass_LABEL = 6, COFF_SymStorageClass_UNDEFINED_LABEL = 7, COFF_SymStorageClass_MEMBER_OF_STRUCT = 8, COFF_SymStorageClass_ARGUMENT = 9, COFF_SymStorageClass_STRUCT_TAG = 10, COFF_SymStorageClass_MEMBER_OF_UNION = 11, COFF_SymStorageClass_UNION_TAG = 12, COFF_SymStorageClass_TYPE_DEFINITION = 13, COFF_SymStorageClass_UNDEFINED_STATIC = 14, COFF_SymStorageClass_ENUM_TAG = 15, COFF_SymStorageClass_MEMBER_OF_ENUM = 16, COFF_SymStorageClass_REGISTER_PARAM = 17, COFF_SymStorageClass_BIT_FIELD = 18, COFF_SymStorageClass_BLOCK = 100, COFF_SymStorageClass_FUNCTION = 101, COFF_SymStorageClass_END_OF_STRUCT = 102, COFF_SymStorageClass_FILE = 103, COFF_SymStorageClass_SECTION = 104, COFF_SymStorageClass_WEAK_EXTERNAL = 105, COFF_SymStorageClass_CLR_TOKEN = 107, COFF_SymStorageClass_COUNT = 27 }; typedef U16 COFF_SymSecNumber; enum { COFF_SymSecNumber_NUMBER_UNDEFINED = 0, COFF_SymSecNumber_ABSOLUTE = 0xffff, COFF_SymSecNumber_DEBUG = 0xfffe, COFF_SymSecNumber_COUNT = 3 }; typedef U8 COFF_SymDType; enum { COFF_SymDType_NULL = 0, COFF_SymDType_PTR = 16, COFF_SymDType_FUNC = 32, COFF_SymDType_ARRAY = 48, COFF_SymDType_COUNT = 4 }; typedef U32 COFF_WeakExtType; enum { COFF_WeakExtType_NOLIBRARY = 1, COFF_WeakExtType_SEARCH_LIBRARY = 2, COFF_WeakExtType_SEARCH_ALIAS = 3, COFF_WeakExtType_COUNT = 3 }; typedef U32 COFF_ImportHeaderType; enum { COFF_ImportHeaderType_CODE = 0, COFF_ImportHeaderType_DATA = 1, COFF_ImportHeaderType_CONST = 2, COFF_ImportHeaderType_COUNT = 3 }; typedef U32 COFF_ImportHeaderNameType; enum { COFF_ImportHeaderNameType_ORDINAL = 0, COFF_ImportHeaderNameType_NAME = 1, COFF_ImportHeaderNameType_NAME_NOPREFIX = 2, COFF_ImportHeaderNameType_UNDECORATE = 3, COFF_ImportHeaderNameType_COUNT = 4 }; #define COFF_IMPORT_HEADER_TYPE_MASK 0x03 #define COFF_IMPORT_HEADER_TYPE_SHIFT 0 #define COFF_IMPORT_HEADER_NAME_TYPE_MASK 0x1c #define COFF_IMPORT_HEADER_NAME_TYPE_SHIFT 2 #define COFF_IMPORT_HEADER_GET_TYPE(x) (((x) & COFF_IMPORT_HEADER_TYPE_MASK) >> COFF_IMPORT_HEADER_TYPE_SHIFT) #define COFF_IMPORT_HEADER_GET_NAME_TYPE(x) (((x) & COFF_IMPORT_HEADER_NAME_TYPE_MASK) >> COFF_IMPORT_HEADER_NAME_TYPE_SHIFT) typedef struct COFF_ImportHeader { U16 sig1; U16 sig2; U16 version; U16 machine; COFF_TimeStamp time_stamp; U32 data_size; U16 hint; U16 type; U16 name_type; // type : 2 // name type : 3 // reserved : 11 //U16 flags; String8 func_name; String8 dll_name; } COFF_ImportHeader; typedef U8 COFF_ComdatSelectType; enum { COFF_ComdatSelectType_NULL = 0, // Only one symbol is allowed to be in global symbol table, otherwise multiply defintion error is thrown. COFF_ComdatSelectType_NODUPLICATES = 1, // Select any symbol, even if there are multiple definitions. (we default to first declaration) COFF_ComdatSelectType_ANY = 2, // Sections that symbols reference must match in size, otherwise multiply definition error is thrown. COFF_ComdatSelectType_SAME_SIZE = 3, // Sections that symbols reference must have identical checksums, otherwise multiply defintion error is thrown. COFF_ComdatSelectType_EXACT_MATCH = 4, // Symbols with associative type form a chain of sections are related to each other. (next link is indicated in COFF_SecDef in 'number') COFF_ComdatSelectType_ASSOCIATIVE = 5, // Linker selects section with largest size. COFF_ComdatSelectType_LARGEST = 6, COFF_ComdatSelectType_COUNT = 7 }; #define COFF_MIN_BIG_OBJ_VERSION 2 global U8 coff_big_obj_magic[] = { 0xC7,0xA1,0xBA,0xD1,0xEE,0xBA,0xA9,0x4B, 0xAF,0x20,0xFA,0xF6,0x6A,0xA4,0xDC,0xB8, }; typedef struct COFF_HeaderBigObj COFF_HeaderBigObj; struct COFF_HeaderBigObj { U16 sig1; // COFF_MachineType_UNKNOWN U16 sig2; // U16_MAX U16 version; U16 machine; U32 time_stamp; U8 magic[16]; U32 unused[4]; U32 section_count; U32 pointer_to_symbol_table; U32 number_of_symbols; }; // Special values for section number field in coff symbol #define COFF_SYMBOL_UNDEFINED_SECTION 0 #define COFF_SYMBOL_ABS_SECTION ((U32)-1) #define COFF_SYMBOL_DEBUG_SECTION ((U32)-2) #define COFF_SYMBOL_ABS_SECTION_16 ((U16)-1) #define COFF_SYMBOL_DEBUG_SECTION_16 ((U16)-2) typedef union COFF_SymbolName COFF_SymbolName; union COFF_SymbolName { U8 short_name[8]; struct { // if this field is filled with zeroes we have a long name, // which means name is stored in the string table // and we need to use the offset to look it up... U32 zeroes; U32 string_table_offset; }long_name; }; typedef struct COFF_Symbol16 COFF_Symbol16; struct COFF_Symbol16 { COFF_SymbolName name; U32 value; U16 section_number; union { struct { COFF_SymDType msb; COFF_SymType lsb; }u; U16 v; }type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; }; typedef struct COFF_Symbol32 COFF_Symbol32; struct COFF_Symbol32 { COFF_SymbolName name; U32 value; U32 section_number; union { struct { COFF_SymDType msb; COFF_SymType lsb; }u; U16 v; }type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; }; // Auxilary symbols are allocated with fixed size so that symbol table could be maintaned as array of regular size. #define COFF_AUX_SYMBOL_SIZE 18 // storage class: FUNCTION typedef struct COFF_SymbolFunc { U8 unused[4]; U16 ln; U8 unused2[2]; U32 ptr_to_next_func; U8 unused3[2]; } COFF_SymbolFunc; // storage class: WEAK_EXTERNAL typedef struct COFF_SymbolWeakExt { U32 tag_index; U32 characteristics; U8 unused[10]; } COFF_SymbolWeakExt; typedef struct COFF_SymbolFile { char name[18]; } COFF_SymbolFile; // provides information about section to which symbol refers to. // storage class: STATIC typedef struct COFF_SymbolSecDef { U32 length; U16 number_of_relocations; U16 number_of_ln; U32 check_sum; U16 number; // one-based section index U8 selection; U8 unused[3]; } COFF_SymbolSecDef; // specifies how section data should be modified when placed in the image file. typedef struct COFF_Reloc COFF_Reloc; struct COFF_Reloc { U32 apply_off; // section relative offset where relocation is placed U32 isymbol; // zero based index into coff symbol table U16 type; // relocation type that depends on the arch }; #pragma pack(pop) // feature flags in absolute symbol @feat.00 enum { COFF_FeatFlag_HAS_SAFE_SEH = (1 << 0), // /safeseh COFF_FeatFlag_UNKNOWN_4 = (1 << 4), COFF_FeatFlag_GUARD_STACK = (1 << 8), // /GS COFF_FeatFlag_SDL = (1 << 9), // /sdl COFF_FeatFlag_GUARD_CF = (1 << 11), // /guard:cf COFF_FeatFlag_GUARD_EH_CONT = (1 << 14), // /guard:ehcont COFF_FeatFlag_NO_RTTI = (1 << 17), // /GR- COFF_FeatFlag_KERNEL = (1 << 30), // /kernel }; typedef U32 COFF_FeatFlags; //////////////////////////////// #define COFF_RES_ALIGN 4u typedef struct COFF_ResourceHeaderPrefix { U32 data_size; U32 header_size; } COFF_ResourceHeaderPrefix; typedef U16 COFF_ResourceMemoryFlags; enum { COFF_ResourceMemoryFlag_MOVEABLE = 0x10, COFF_ResourceMemoryFlag_PURE = 0x20, COFF_ResourceMemoryFlag_PRELOAD = 0x40, COFF_ResourceMemoryFlag_DISCARDABLE = 0x1000, }; typedef enum { COFF_ResourceIDType_NULL, COFF_ResourceIDType_NUMBER, COFF_ResourceIDType_STRING, COFF_ResourceIDType_COUNT } COFF_ResourceIDType; typedef struct COFF_ResourceID_16 { COFF_ResourceIDType type; union { U16 number; String16 string; } u; } COFF_ResourceID_16; typedef struct COFF_ResourceID { COFF_ResourceIDType type; union { U16 number; String8 string; } u; } COFF_ResourceID; typedef struct COFF_Resource { COFF_ResourceID type; COFF_ResourceID name; U16 language_id; U32 data_version; U32 version; COFF_ResourceMemoryFlags memory_flags; String8 data; } COFF_Resource; typedef struct COFF_ResourceDataEntry { U32 data_voff; U32 data_size; U32 code_page; U32 reserved; } COFF_ResourceDataEntry; typedef struct COFF_ResourceDirTable { U32 characteristics; COFF_TimeStamp time_stamp; U16 major_version; U16 minor_version; U16 name_entry_count; U16 id_entry_count; } COFF_ResourceDirTable; #define COFF_RESOURCE_SUB_DIR_FLAG (1u << 31u) typedef struct COFF_ResourceDirEntry { union { U32 offset; U32 id; } name; union { U32 data_entry_offset; U32 sub_dir_offset; } id; } COFF_ResourceDirEntry; //////////////////////////////// // !\n #define COFF_ARCHIVE_SIG 0x0A3E686372613C21ULL // !\n #define COFF_THIN_ARCHIVE_SIG 0xA3E6E6968743C21ULL #define COFF_ARCHIVE_MAX_SHORT_NAME_SIZE 15 #define COFF_ARCHIVE_ALIGN 2 typedef struct COFF_ArchiveMemberHeader { String8 name; // padded to 16 bytes with spaces U32 date; // unix time U32 user_id; // unix artifact that does not have meaning on windows U32 group_id; // unix artifact that does not have meaning on windows String8 mode; // octal representation the members file mode U32 size; // size of the member data, not including header B32 is_end_correct; // set to true if found correct signature after header } COFF_ArchiveMemberHeader; //////////////////////////////// // Helpers enum { COFF_DataType_NULL, COFF_DataType_BIG_OBJ, COFF_DataType_OBJ, COFF_DataType_IMPORT, }; typedef U32 COFF_DataType; typedef struct COFF_HeaderInfo { COFF_MachineType machine; U64 section_array_off; U64 section_count_no_null; U64 string_table_off; U64 symbol_size; U64 symbol_off; U64 symbol_count; } COFF_HeaderInfo; enum { // symbol has section and offset. COFF_SymbolValueInterp_REGULAR, // symbol is overridable COFF_SymbolValueInterp_WEAK, // symbol doesn't have a reference section. COFF_SymbolValueInterp_UNDEFINED, // symbol has no section but still has size. COFF_SymbolValueInterp_COMMON, // symbol has an absolute (non-relocatable) value and is not an address. COFF_SymbolValueInterp_ABS, // symbol is used to provide general type of debugging information. COFF_SymbolValueInterp_DEBUG }; typedef U32 COFF_SymbolValueInterpType; typedef struct COFF_Symbol16Node { struct COFF_Symbol16Node *next; COFF_Symbol16 data; } COFF_Symbol16Node; typedef struct COFF_Symbol16List { U64 count; COFF_Symbol16Node *first; COFF_Symbol16Node *last; } COFF_Symbol16List; typedef struct COFF_Symbol32Array { U64 count; COFF_Symbol32 *v; } COFF_Symbol32Array; typedef struct COFF_RelocNode { struct COFF_RelocNode *next; COFF_Reloc data; } COFF_RelocNode; typedef struct COFF_RelocList { U64 count; COFF_RelocNode *first; COFF_RelocNode *last; } COFF_RelocList; typedef struct COFF_RelocArray { U64 count; COFF_Reloc *v; } COFF_RelocArray; typedef struct COFF_RelocInfo { U64 array_off; U64 count; } COFF_RelocInfo; typedef struct COFF_ResourceNode { struct COFF_ResourceNode *next; COFF_Resource data; } COFF_ResourceNode; typedef struct COFF_ResourceList { U64 count; COFF_ResourceNode *first; COFF_ResourceNode *last; } COFF_ResourceList; //////////////////////////////// typedef struct COFF_ArchiveMember { COFF_ArchiveMemberHeader header; U64 offset; String8 data; } COFF_ArchiveMember; typedef struct COFF_ArchiveFirstMember { U32 symbol_count; String8 member_offsets; String8 string_table; } COFF_ArchiveFirstMember; typedef struct COFF_ArchiveSecondMember { U32 member_count; U32 symbol_count; String8 member_offsets; String8 symbol_indices; String8 string_table; } COFF_ArchiveSecondMember; typedef struct COFF_ArchiveMemberNode { struct COFF_ArchiveMemberNode *next; COFF_ArchiveMember data; } COFF_ArchiveMemberNode; typedef struct COFF_ArchiveMemberList { U64 count; COFF_ArchiveMemberNode *first; COFF_ArchiveMemberNode *last; } COFF_ArchiveMemberList; typedef enum { COFF_Archive_Null, COFF_Archive_Regular, COFF_Archive_Thin } COFF_ArchiveType; typedef struct COFF_ArchiveParse { COFF_ArchiveFirstMember first_member; COFF_ArchiveSecondMember second_member; String8 long_names; } COFF_ArchiveParse; //////////////////////////////// //~ rjf: Globals read_only global COFF_SectionHeader coff_section_header_nil = {0}; //////////////////////////////// //~ rjf: Helper Functions internal B32 coff_is_big_obj(String8 data); internal B32 coff_is_obj(String8 data); internal COFF_HeaderInfo coff_header_info_from_data(String8 data); internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags); internal COFF_SymbolValueInterpType coff_interp_symbol(COFF_Symbol32 *symbol); internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff); internal COFF_SectionHeader *coff_section_header_from_num(String8 data, U64 section_headers_off, U64 n); internal String8 coff_section_header_get_name(COFF_SectionHeader *header, String8 coff_data, U64 string_table_base); internal void coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_out); internal String8 coff_read_symbol_name(String8 data, U64 string_table_base_offset, COFF_SymbolName *name); internal void coff_symbol32_from_coff_symbol16(COFF_Symbol32 *sym32, COFF_Symbol16 *sym16); internal COFF_Symbol32Array coff_symbol_array_from_data_16(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count); internal COFF_Symbol32Array coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count); internal COFF_Symbol32Array coff_symbol_array_from_data(Arena *arena, String8 data, U64 symbol_off, U64 symbol_count, U64 symbol_size); internal COFF_Symbol16Node * coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol); internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header); internal U64 coff_word_size_from_machine(COFF_MachineType machine); internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name); internal U32 coff_make_ordinal_32(U16 hint); internal U64 coff_make_ordinal_64(U16 hint); internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b); internal COFF_ResourceID coff_resource_id_copy(Arena *arena, COFF_ResourceID id); internal COFF_ResourceID coff_convert_resource_id(Arena *arena, COFF_ResourceID_16 *id_16); internal U64 coff_read_resource_id(String8 res, U64 off, COFF_ResourceID_16 *id_out); internal U64 coff_read_resource(String8 data, U64 off, Arena *arena, COFF_Resource *res_out); internal COFF_ResourceList coff_resource_list_from_data(Arena *arena, String8 data); internal COFF_DataType coff_data_type_from_data(String8 data); internal B32 coff_is_import(String8 data); internal B32 coff_is_archive(String8 data); internal B32 coff_is_thin_archive(String8 data); internal U64 coff_read_archive_member_header(String8 data, U64 offset, COFF_ArchiveMemberHeader *header_out); internal COFF_ArchiveMember coff_read_archive_member(String8 data, U64 offset); internal U64 coff_read_archive_import(String8 data, U64 offset, COFF_ImportHeader *header_out); internal String8 coff_read_archive_long_name(String8 long_names, String8 name); internal COFF_ArchiveMember coff_archive_member_from_data(String8 data); internal U64 coff_archive_member_iter_init(String8 data); internal B32 coff_archive_member_iter_next(String8 data, U64 *offset, COFF_ArchiveMember *member_out); internal COFF_ArchiveParse coff_archive_parse_from_member_list(COFF_ArchiveMemberList list); internal COFF_ArchiveParse coff_archive_from_data(Arena *arena, String8 data); internal U64 coff_thin_archive_member_iter_init(String8 data); internal B32 coff_thin_archive_member_iter_next(String8 data, U64 *offset, COFF_ArchiveMember *member_out); internal COFF_ArchiveParse coff_thin_archive_from_data(Arena *arena, String8 data); internal COFF_ArchiveType coff_archive_type_from_data(String8 data); internal COFF_ArchiveParse coff_archive_parse_from_data(Arena *arena, String8 data); internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType select); internal String8 coff_string_from_machine_type(COFF_MachineType machine); internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags); #endif //COFF_H