diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 9ff233a3..4836c249 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -14,30 +14,30 @@ cv_arch_from_coff_machine(COFF_MachineType machine) CV_Arch arch = 0; switch(machine) { - case COFF_MachineType_X64: arch = CV_Arch_X64; break; - case COFF_MachineType_X86: arch = CV_Arch_8086; break; - case COFF_MachineType_AM33: arch = CV_Arch_AM33; break; - case COFF_MachineType_ARM: NotImplemented; break; - case COFF_MachineType_ARM64: arch = CV_Arch_ARM64; break; - case COFF_MachineType_ARMNT: arch = CV_Arch_ARMNT; break; - case COFF_MachineType_EBC: arch = CV_Arch_EBC; break; - case COFF_MachineType_IA64: arch = CV_Arch_IA64; break; - case COFF_MachineType_M32R: arch = CV_Arch_M32R; break; - case COFF_MachineType_MIPS16: arch = CV_Arch_MIPS16; break; - case COFF_MachineType_MIPSFPU: NotImplemented; break; - case COFF_MachineType_MIPSFPU16: NotImplemented; break; - case COFF_MachineType_POWERPC: NotImplemented; break; - case COFF_MachineType_POWERPCFP: arch = CV_Arch_PPCFP; break; - case COFF_MachineType_R4000: NotImplemented; break; - case COFF_MachineType_RISCV32: NotImplemented; break; - case COFF_MachineType_RISCV64: NotImplemented; break; - case COFF_MachineType_RISCV128: NotImplemented; break; - case COFF_MachineType_SH3: arch = CV_Arch_SH3; break; - case COFF_MachineType_SH3DSP: arch = CV_Arch_SH3DSP; break; - case COFF_MachineType_SH4: arch = CV_Arch_SH4; break; - case COFF_MachineType_SH5: NotImplemented; break; - case COFF_MachineType_THUMB: arch = CV_Arch_THUMB; break; - case COFF_MachineType_WCEMIPSV2: NotImplemented; break; + case COFF_Machine_X64: arch = CV_Arch_X64; break; + case COFF_Machine_X86: arch = CV_Arch_8086; break; + case COFF_Machine_Am33: arch = CV_Arch_AM33; break; + case COFF_Machine_Arm: NotImplemented; break; + case COFF_Machine_Arm64: arch = CV_Arch_ARM64; break; + case COFF_Machine_ArmNt: arch = CV_Arch_ARMNT; break; + case COFF_Machine_Ebc: arch = CV_Arch_EBC; break; + case COFF_Machine_Ia64: arch = CV_Arch_IA64; break; + case COFF_Machine_M32R: arch = CV_Arch_M32R; break; + case COFF_Machine_Mips16: arch = CV_Arch_MIPS16; break; + case COFF_Machine_MipsFpu: NotImplemented; break; + case COFF_Machine_MipsFpu16: NotImplemented; break; + case COFF_Machine_PowerPc: NotImplemented; break; + case COFF_Machine_PowerPcFp: arch = CV_Arch_PPCFP; break; + case COFF_Machine_R4000: NotImplemented; break; + case COFF_Machine_RiscV32: NotImplemented; break; + case COFF_Machine_RiscV64: NotImplemented; break; + case COFF_Machine_RiscV128: NotImplemented; break; + case COFF_Machine_Sh3: arch = CV_Arch_SH3; break; + case COFF_Machine_Sh3Dsp: arch = CV_Arch_SH3DSP; break; + case COFF_Machine_Sh4: arch = CV_Arch_SH4; break; + case COFF_Machine_Sh5: NotImplemented; break; + case COFF_Machine_Thumb: arch = CV_Arch_THUMB; break; + case COFF_Machine_WceMipsV2: NotImplemented; break; } return arch; } diff --git a/src/coff/coff.c b/src/coff/coff.c index 1e9c2487..0f2ba099 100644 --- a/src/coff/coff.c +++ b/src/coff/coff.c @@ -1,148 +1,28 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -internal B32 -coff_is_big_obj(String8 data) -{ - B32 is_big_obj = 0; - if (data.size >= sizeof(COFF_HeaderBigObj)) { - COFF_HeaderBigObj *big_header = (COFF_HeaderBigObj*)(data.str); - is_big_obj = big_header->sig1 == COFF_MachineType_UNKNOWN && - big_header->sig2 == max_U16 && - big_header->version >= COFF_MIN_BIG_OBJ_VERSION && - MemoryCompare(big_header->magic, coff_big_obj_magic, sizeof(big_header->magic)) == 0; - } - return is_big_obj; -} - -internal B32 -coff_is_obj(String8 data) -{ - B32 is_obj = 0; - - if (data.size >= sizeof(COFF_Header)) { - COFF_Header *header = (COFF_Header*)(data.str); - - // validate machine - B32 is_machine_type_valid = 0; - switch (header->machine) { - case COFF_MachineType_UNKNOWN: - case COFF_MachineType_X86: case COFF_MachineType_X64: - case COFF_MachineType_AM33: case COFF_MachineType_ARM: - case COFF_MachineType_ARM64: case COFF_MachineType_ARMNT: - case COFF_MachineType_EBC: case COFF_MachineType_IA64: - case COFF_MachineType_M32R: case COFF_MachineType_MIPS16: - case COFF_MachineType_MIPSFPU:case COFF_MachineType_MIPSFPU16: - case COFF_MachineType_POWERPC:case COFF_MachineType_POWERPCFP: - case COFF_MachineType_R4000: case COFF_MachineType_RISCV32: - case COFF_MachineType_RISCV64:case COFF_MachineType_RISCV128: - case COFF_MachineType_SH3: case COFF_MachineType_SH3DSP: - case COFF_MachineType_SH4: case COFF_MachineType_SH5: - case COFF_MachineType_THUMB: case COFF_MachineType_WCEMIPSV2: - { - is_machine_type_valid = 1; - }break; - } - - if (is_machine_type_valid) { - // validate section count - U64 section_count = header->section_count; - U64 section_hdr_opl_off = sizeof(*header) + section_count*sizeof(COFF_SectionHeader); - if (data.size >= section_hdr_opl_off) { - - COFF_SectionHeader *section_hdrs = (COFF_SectionHeader*)(data.str + sizeof(*header)); - COFF_SectionHeader *section_hdr_opl = section_hdrs + section_count; - - // validate section ranges - B32 is_sect_range_valid = 1; - for (COFF_SectionHeader *sec_hdr = section_hdrs; - sec_hdr < section_hdr_opl; - sec_hdr += 1) { - if (!(sec_hdr->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA)) { - U64 min = sec_hdr->foff; - U64 max = min + sec_hdr->fsize; - if (sec_hdr->fsize > 0 && !(section_hdr_opl_off <= min && min <= max && max <= data.size)) { - is_sect_range_valid = 0; - break; - } - } - } - - if (is_sect_range_valid) { - // validate symbol table - U64 symbol_table_off = header->symbol_table_foff; - U64 symbol_table_size = sizeof(COFF_Symbol16)*header->symbol_count; - U64 symbol_table_opl_off = symbol_table_off + symbol_table_size; - - // don't validate symbol table when there is none - if (symbol_table_off == 0 && symbol_table_size == 0) { - symbol_table_off = section_hdr_opl_off; - symbol_table_opl_off = section_hdr_opl_off; - } - - is_obj = (section_hdr_opl_off <= symbol_table_off && - symbol_table_off <= symbol_table_opl_off && - symbol_table_opl_off <= data.size); - } - } - } - } - - return is_obj; -} - -internal COFF_HeaderInfo -coff_header_info_from_data(String8 data) -{ - COFF_HeaderInfo info = {0}; - if (coff_is_big_obj(data)) { - COFF_HeaderBigObj *big_header = (COFF_HeaderBigObj*)data.str; - info.type = COFF_DataType_BIG_OBJ; - info.machine = big_header->machine; - info.header_size = sizeof(COFF_HeaderBigObj); - info.section_array_off = sizeof(COFF_HeaderBigObj); - info.section_count_no_null = big_header->section_count; - info.string_table_off = big_header->symbol_table_foff + sizeof(COFF_Symbol32) * big_header->symbol_count; - info.symbol_size = sizeof(COFF_Symbol32); - info.symbol_off = big_header->symbol_table_foff; - info.symbol_count = big_header->symbol_count; - } else if (coff_is_obj(data)) { - COFF_Header *header = (COFF_Header*)data.str; - info.type = COFF_DataType_OBJ; - info.machine = header->machine; - info.header_size = sizeof(COFF_Header); - info.section_array_off = sizeof(COFF_Header); - info.section_count_no_null = header->section_count; - info.string_table_off = header->symbol_table_foff + sizeof(COFF_Symbol16) * header->symbol_count; - info.symbol_size = sizeof(COFF_Symbol16); - info.symbol_off = header->symbol_table_foff; - info.symbol_count = header->symbol_count; - } - return info; -} - internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags) { U32 align = 0; - U32 align_index = COFF_SectionFlags_Extract_ALIGN(flags); + U32 align_index = COFF_SectionFlags_ExtractAlign(flags); switch (align_index) { default: break; case 0: align = 1; break; // alignment isn't specified, default to 1 - case COFF_SectionAlign_1BYTES: align = 1; break; - case COFF_SectionAlign_2BYTES: align = 2; break; - case COFF_SectionAlign_4BYTES: align = 4; break; - case COFF_SectionAlign_8BYTES: align = 8; break; - case COFF_SectionAlign_16BYTES: align = 16; break; - case COFF_SectionAlign_32BYTES: align = 32; break; - case COFF_SectionAlign_64BYTES: align = 64; break; - case COFF_SectionAlign_128BYTES: align = 128; break; - case COFF_SectionAlign_256BYTES: align = 256; break; - case COFF_SectionAlign_512BYTES: align = 512; break; - case COFF_SectionAlign_1024BYTES: align = 1024; break; - case COFF_SectionAlign_2048BYTES: align = 2048; break; - case COFF_SectionAlign_4096BYTES: align = 4096; break; - case COFF_SectionAlign_8192BYTES: align = 8192; break; + case COFF_SectionAlign_1Bytes: align = 1; break; + case COFF_SectionAlign_2Bytes: align = 2; break; + case COFF_SectionAlign_4Bytes: align = 4; break; + case COFF_SectionAlign_8Bytes: align = 8; break; + case COFF_SectionAlign_16Bytes: align = 16; break; + case COFF_SectionAlign_32Bytes: align = 32; break; + case COFF_SectionAlign_64Bytes: align = 64; break; + case COFF_SectionAlign_128Bytes: align = 128; break; + case COFF_SectionAlign_256Bytes: align = 256; break; + case COFF_SectionAlign_512Bytes: align = 512; break; + case COFF_SectionAlign_1024Bytes: align = 1024; break; + case COFF_SectionAlign_2048Bytes: align = 2048; break; + case COFF_SectionAlign_4096Bytes: align = 4096; break; + case COFF_SectionAlign_8192Bytes: align = 8192; break; } return align; } @@ -152,101 +32,35 @@ coff_section_flag_from_align_size(U64 align) { COFF_SectionFlags flags = 0; switch (align) { - case 1: flags = COFF_SectionAlign_1BYTES; break; - case 2: flags = COFF_SectionAlign_2BYTES; break; - case 4: flags = COFF_SectionAlign_4BYTES; break; - case 8: flags = COFF_SectionAlign_8BYTES; break; - case 16: flags = COFF_SectionAlign_16BYTES; break; - case 32: flags = COFF_SectionAlign_32BYTES; break; - case 64: flags = COFF_SectionAlign_64BYTES; break; - case 128: flags = COFF_SectionAlign_128BYTES; break; - case 256: flags = COFF_SectionAlign_256BYTES; break; - case 512: flags = COFF_SectionAlign_512BYTES; break; - case 1024: flags = COFF_SectionAlign_1024BYTES; break; - case 2048: flags = COFF_SectionAlign_2048BYTES; break; - case 4096: flags = COFF_SectionAlign_4096BYTES; break; - case 8192: flags = COFF_SectionAlign_8192BYTES; break; + case 1: flags = COFF_SectionAlign_1Bytes; break; + case 2: flags = COFF_SectionAlign_2Bytes; break; + case 4: flags = COFF_SectionAlign_4Bytes; break; + case 8: flags = COFF_SectionAlign_8Bytes; break; + case 16: flags = COFF_SectionAlign_16Bytes; break; + case 32: flags = COFF_SectionAlign_32Bytes; break; + case 64: flags = COFF_SectionAlign_64Bytes; break; + case 128: flags = COFF_SectionAlign_128Bytes; break; + case 256: flags = COFF_SectionAlign_256Bytes; break; + case 512: flags = COFF_SectionAlign_512Bytes; break; + case 1024: flags = COFF_SectionAlign_1024Bytes; break; + case 2048: flags = COFF_SectionAlign_2048Bytes; break; + case 4096: flags = COFF_SectionAlign_4096Bytes; break; + case 8192: flags = COFF_SectionAlign_8192Bytes; break; } - flags <<= COFF_SectionFlag_ALIGN_SHIFT; + flags <<= COFF_SectionFlag_AlignShift; return flags; } -internal COFF_SymbolValueInterpType -coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class) -{ - if (storage_class == COFF_SymStorageClass_SECTION && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { - return COFF_SymbolValueInterp_UNDEFINED; - } - if (storage_class == COFF_SymStorageClass_EXTERNAL && value == 0 && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { - return COFF_SymbolValueInterp_UNDEFINED; - } - if (storage_class == COFF_SymStorageClass_EXTERNAL && value != 0 && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { - return COFF_SymbolValueInterp_COMMON; - } - if (section_number == COFF_SYMBOL_ABS_SECTION) { - return COFF_SymbolValueInterp_ABS; - } - if (section_number == COFF_SYMBOL_DEBUG_SECTION) { - return COFF_SymbolValueInterp_DEBUG; - } - if (storage_class == COFF_SymStorageClass_WEAK_EXTERNAL) { - return COFF_SymbolValueInterp_WEAK; - } - return COFF_SymbolValueInterp_REGULAR; -} - -internal U64 -coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff) -{ - U64 foff = 0; - for(U64 sect_idx = 0; sect_idx < section_count; sect_idx += 1) - { - COFF_SectionHeader *sect = §ions[sect_idx]; - if(sect->voff <= voff && voff < sect->voff+sect->vsize) - { - if(!(sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA)) - { - foff = sect->foff + (voff - sect->voff); - } - break; - } - } - return foff; -} - -internal COFF_SectionHeader * -coff_section_header_from_num(String8 data, U64 section_headers_off, U64 n) -{ - COFF_SectionHeader *result = &coff_section_header_nil; - if(1 <= n && section_headers_off + n*sizeof(COFF_SectionHeader) <= data.size) - { - result = (COFF_SectionHeader*)(data.str + section_headers_off + (n-1)*sizeof(COFF_SectionHeader)); - } - return result; -} - internal String8 -coff_name_from_section_header(COFF_SectionHeader *header, String8 coff_data, U64 string_table_base) +coff_name_from_section_header(String8 raw_coff, COFF_SectionHeader *header, U64 string_table_off) { - U64 size = 0; - for (; size < sizeof(header->name); size += 1) { - if (header->name[size] == '\0') { - break; - } - } - String8 name = str8(header->name, size); - + String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name)); if (name.str[0] == '/') { - String8 ascii_name_offset = str8_skip(name, 1); - U64 name_offset = u64_from_str8(ascii_name_offset, 10); - - name_offset += string_table_base; - if (name_offset < coff_data.size) { - char *ptr = (char *)coff_data.str + name_offset; - name = str8_cstring(ptr); - } + String8 ascii_off = str8_skip(name, 1); + U64 name_rel_off = u64_from_str8(ascii_off, 10); + U64 name_off = name_rel_off + string_table_off; + name = str8_cstring_capped(raw_coff.str + name_off, raw_coff.str + raw_coff.size); } - return name; } @@ -261,11 +75,11 @@ coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_o // P: Precompiled types // F: FPO data // H: Clang extension produced with /debug:ghash, array of type hashes - *name_out = full_name; + *name_out = full_name; *postfix_out = str8_lit(""); for (U64 i = 0; i < full_name.size; ++i) { if (full_name.str[i] == '$') { - *name_out = str8(full_name.str, i); + *name_out = str8(full_name.str, i); *postfix_out = str8(full_name.str + i + 1, full_name.size - i - 1); // TLS sections don't have a postfix but we still have to sort them based @@ -279,25 +93,13 @@ coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_o } } -internal COFF_RelocNode * -coff_reloc_list_push(Arena *arena, COFF_RelocList *list, COFF_Reloc reloc) -{ - COFF_RelocNode *node = push_array(arena, COFF_RelocNode, 1); - node->data = reloc; - SLLQueuePush(list->first, list->last, node); - ++list->count; - return node; -} - -//////////////////////////////// - internal String8 -coff_read_symbol_name(String8 data, U64 string_table_base_offset, COFF_SymbolName *name) +coff_read_symbol_name(String8 raw_coff, U64 string_table_off, COFF_SymbolName *name) { String8 name_str = str8_lit(""); if (name->long_name.zeroes == 0) { - U64 string_table_offset = string_table_base_offset + name->long_name.string_table_offset; - str8_deserial_read_cstr(data, string_table_offset, &name_str); + U64 name_string_off = string_table_off + name->long_name.string_table_offset; + str8_deserial_read_cstr(raw_coff, name_string_off, &name_str); } else { U32 i; for (i = 0; i < sizeof(name->short_name); ++i) { @@ -310,160 +112,28 @@ coff_read_symbol_name(String8 data, U64 string_table_base_offset, COFF_SymbolNam return name_str; } -internal COFF_ParsedSymbol -coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32) -{ - COFF_ParsedSymbol result = {0}; - result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym32->name); - result.value = sym32->value; - result.section_number = sym32->section_number; - result.type = sym32->type; - result.storage_class = sym32->storage_class; - result.aux_symbol_count = sym32->aux_symbol_count; - return result; -} - -internal COFF_ParsedSymbol -coff_parse_symbol16(String8 raw_coff, U64 string_table_off, COFF_Symbol16 *sym16) -{ - COFF_ParsedSymbol result = {0}; - result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym16->name); - result.value = sym16->value; - if (sym16->section_number == COFF_SYMBOL_DEBUG_SECTION_16) { - result.section_number = COFF_SYMBOL_DEBUG_SECTION; - } else if (sym16->section_number == COFF_SYMBOL_ABS_SECTION_16) { - result.section_number = COFF_SYMBOL_ABS_SECTION; - } else { - result.section_number = (U32)sym16->section_number; - } - result.type = sym16->type; - result.storage_class = sym16->storage_class; - result.aux_symbol_count = sym16->aux_symbol_count; - return result; -} - -internal void -coff_symbol32_from_coff_symbol16(COFF_Symbol32 *sym32, COFF_Symbol16 *sym16) -{ - sym32->name = sym16->name; - sym32->value = sym16->value; - if (sym16->section_number == COFF_SYMBOL_DEBUG_SECTION_16) { - sym32->section_number = COFF_SYMBOL_DEBUG_SECTION; - } else if (sym16->section_number == COFF_SYMBOL_ABS_SECTION_16) { - sym32->section_number = COFF_SYMBOL_ABS_SECTION; - } else { - sym32->section_number = (U32)sym16->section_number; - } - sym32->type.v = sym16->type.v; - sym32->storage_class = sym16->storage_class; - sym32->aux_symbol_count = sym16->aux_symbol_count; -} - -internal COFF_Symbol32Array -coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count) -{ - COFF_Symbol32Array result = {0}; - result.count = symbol_count; - result.v = push_array_no_zero_aligned(arena, COFF_Symbol32, result.count, 8); - - Rng1U64 sym16_arr_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count); - String8 raw_sym16_arr = str8_substr(raw_coff, sym16_arr_range); - COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)raw_sym16_arr.str; - - for (U64 isymbol = 0, count = raw_sym16_arr.size / sizeof(COFF_Symbol16); isymbol < count; isymbol += 1) { - COFF_Symbol16 *sym16 = &sym16_arr[isymbol]; - COFF_Symbol32 *sym32 = &result.v[isymbol]; - - coff_symbol32_from_coff_symbol16(sym32, sym16); - - // copy aux symbols - for (U64 iaux = isymbol+1, iaux_hi = Min(count, iaux+sym16->aux_symbol_count); iaux < iaux_hi; iaux += 1) { - COFF_Symbol16 *aux16 = sym16_arr + iaux; - COFF_Symbol32 *aux32 = result.v + iaux; - - // 32bit COFF uses 16bit aux symbols - MemoryCopy(aux32, aux16, sizeof(COFF_Symbol16)); - MemoryZero((U8 *)aux32 + sizeof(COFF_Symbol16), sizeof(COFF_Symbol32)-sizeof(COFF_Symbol16)); - } - - // take into account aux symbols - isymbol += sym32->aux_symbol_count; - } - - return result; -} - -internal COFF_Symbol32Array -coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count) -{ - COFF_Symbol32Array result; - result.count = symbol_count; - result.v = (COFF_Symbol32 *)(data.str + symbol_array_off); - return result; -} - -internal COFF_Symbol32Array -coff_symbol_array_from_data(Arena *arena, String8 data, U64 symbol_off, U64 symbol_count, U64 symbol_size) -{ - COFF_Symbol32Array result = {0}; - switch (symbol_size) { - case sizeof(COFF_Symbol16): result = coff_symbol_array_from_data_16(arena, data, symbol_off, symbol_count); break; - case sizeof(COFF_Symbol32): result = coff_symbol_array_from_data_32(arena, data, symbol_off, symbol_count); break; - } - return result; -} - -internal COFF_Symbol16Node * -coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol) -{ - COFF_Symbol16Node *node = push_array(arena, COFF_Symbol16Node, 1); - node->next = 0; - node->data = symbol; - SLLQueuePush(list->first, list->last, node); - list->count += 1; - return node; -} - -internal COFF_RelocInfo -coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header) -{ - COFF_RelocInfo result = {0}; - if (header->flags & COFF_SectionFlag_LNK_NRELOC_OVFL && header->reloc_count == max_U16) { - COFF_Reloc counter; - U64 read_size = str8_deserial_read_struct(data, header->relocs_foff, &counter); - if (read_size == sizeof(counter) && counter.apply_off > 0) { - result.array_off = header->relocs_foff + sizeof(COFF_Reloc); - result.count = counter.apply_off - 1; // exclude counter entry - } - } else { - result.array_off = header->relocs_foff; - result.count = header->reloc_count; - } - return result; -} - internal U64 -coff_apply_size_from_reloc_x64(COFF_RelocTypeX64 x) +coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x) { switch (x) { - case COFF_RelocTypeX64_ABS: return 4; - case COFF_RelocTypeX64_ADDR64: return 8; - case COFF_RelocTypeX64_ADDR32: return 4; - case COFF_RelocTypeX64_ADDR32NB: return 4; - case COFF_RelocTypeX64_REL32: return 4; - case COFF_RelocTypeX64_REL32_1: return 4; - case COFF_RelocTypeX64_REL32_2: return 4; - case COFF_RelocTypeX64_REL32_3: return 4; - case COFF_RelocTypeX64_REL32_4: return 4; - case COFF_RelocTypeX64_REL32_5: return 4; - case COFF_RelocTypeX64_SECTION: return 2; - case COFF_RelocTypeX64_SECREL: return 4; - case COFF_RelocTypeX64_SREL32: return 4; + case COFF_Reloc_X64_Abs: return 4; + case COFF_Reloc_X64_Addr64: return 8; + case COFF_Reloc_X64_Addr32: return 4; + case COFF_Reloc_X64_Addr32Nb: return 4; + case COFF_Reloc_X64_Rel32: return 4; + case COFF_Reloc_X64_Rel32_1: return 4; + case COFF_Reloc_X64_Rel32_2: return 4; + case COFF_Reloc_X64_Rel32_3: return 4; + case COFF_Reloc_X64_Rel32_4: return 4; + case COFF_Reloc_X64_Rel32_5: return 4; + case COFF_Reloc_X64_Section: return 2; + case COFF_Reloc_X64_SecRel: return 4; + case COFF_Reloc_X64_SRel32: return 4; - case COFF_RelocTypeX64_SECREL7: - case COFF_RelocTypeX64_TOKEN: - case COFF_RelocTypeX64_PAIR: - case COFF_RelocTypeX64_SSPAN32: + case COFF_Reloc_X64_SecRel7: + case COFF_Reloc_X64_Token: + case COFF_Reloc_X64_Pair: + case COFF_Reloc_X64_SSpan32: NotImplemented; break; } @@ -471,29 +141,29 @@ coff_apply_size_from_reloc_x64(COFF_RelocTypeX64 x) } internal U64 -coff_apply_size_from_reloc_x86(COFF_RelocTypeX86 x) +coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x) { switch (x) { - case COFF_RelocTypeX86_ABS: return 4; - case COFF_RelocTypeX86_DIR16: return 2; - case COFF_RelocTypeX86_REL16: return 2; - case COFF_RelocTypeX86_DIR32: return 4; - case COFF_RelocTypeX86_DIR32NB: return 4; - case COFF_RelocTypeX86_SEG12: return 0; - case COFF_RelocTypeX86_SECTION: return 2; - case COFF_RelocTypeX86_SECREL: return 4; - case COFF_RelocTypeX86_TOKEN: return 4; - case COFF_RelocTypeX86_SECREL7: return 1; - case COFF_RelocTypeX86_REL32: return 4; + case COFF_Reloc_X86_Abs: return 4; + case COFF_Reloc_X86_Dir16: return 2; + case COFF_Reloc_X86_Rel16: return 2; + case COFF_Reloc_X86_Dir32: return 4; + case COFF_Reloc_X86_Dir32Nb: return 4; + case COFF_Reloc_X86_Seg12: return 0; + case COFF_Reloc_X86_Section: return 2; + case COFF_Reloc_X86_SecRel: return 4; + case COFF_Reloc_X86_Token: return 4; + case COFF_Reloc_X86_SecRel7: return 1; + case COFF_Reloc_X86_Rel32: return 4; - case COFF_RelocTypeX86_UNKNOWN0: - case COFF_RelocTypeX86_UNKNOWN2: - case COFF_RelocTypeX86_UNKNOWN3: - case COFF_RelocTypeX86_UNKNOWN4: - case COFF_RelocTypeX86_UNKNOWN6: - case COFF_RelocTypeX86_UNKNOWN7: - case COFF_RelocTypeX86_UNKNOWN8: - case COFF_RelocTypeX86_UNKNOWN9: + case COFF_Reloc_X86_Unknown0: + case COFF_Reloc_X86_Unknown2: + case COFF_Reloc_X86_Unknown3: + case COFF_Reloc_X86_Unknown4: + case COFF_Reloc_X86_Unknown6: + case COFF_Reloc_X86_Unknown7: + case COFF_Reloc_X86_Unknown8: + case COFF_Reloc_X86_Unknown9: NotImplemented; break; } @@ -504,20 +174,132 @@ internal U64 coff_apply_size_from_reloc(COFF_MachineType machine, COFF_RelocType x) { switch (machine) { - case COFF_MachineType_X64: return coff_apply_size_from_reloc_x64(x); - case COFF_MachineType_X86: return coff_apply_size_from_reloc_x86(x); + case COFF_Machine_X64: return coff_apply_size_from_reloc_x64(x); + case COFF_Machine_X86: return coff_apply_size_from_reloc_x86(x); default: NotImplemented; } return 0; } +internal String8 +coff_make_import_lookup(Arena *arena, U16 hint, String8 name) +{ + U64 buffer_size = sizeof(hint) + (name.size + 1); + U8 *buffer = push_array(arena, U8, buffer_size); + *(U16*)buffer = hint; + MemoryCopy(buffer + sizeof(hint), name.str, name.size); + buffer[buffer_size - 1] = 0; + String8 result = str8(buffer, buffer_size); + return result; +} + +internal U32 +coff_make_ordinal32(U16 hint) +{ + U32 ordinal = (1 << 31) | hint; + return ordinal; +} + +internal U64 +coff_make_ordinal64(U16 hint) +{ + U64 ordinal = (1ULL << 63) | hint; + return ordinal; +} + +internal String8 +coff_make_import_header_by_name(Arena *arena, + String8 dll_name, + COFF_MachineType machine, + COFF_TimeStamp time_stamp, + String8 name, + U16 hint, + COFF_ImportType type) +{ + COFF_ImportHeaderFlags flags = 0; + flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift; + flags |= COFF_ImportBy_Name << COFF_ImportHeader_ImportByShift; + + COFF_ImportHeader header = {0}; + header.sig1 = COFF_Machine_Unknown; + header.sig2 = max_U16; + header.version = 0; + header.machine = machine; + header.time_stamp = time_stamp; + header.data_size = safe_cast_u32(name.size + dll_name.size + 2); + header.hint_or_ordinal = hint; + header.flags = flags; + + // alloc memory + U64 buffer_size = sizeof(header) + header.data_size; + U8 *buffer = push_array_no_zero(arena, U8, buffer_size); + + // copy header + MemoryCopy(buffer, &header, sizeof(header)); + + // copy function name + U8 *func_name = buffer + sizeof(header); + MemoryCopy(func_name, name.str, name.size); + func_name[name.size] = 0; + + // copy dll name + U8 *dll_name_buffer = buffer + sizeof(header) + name.size + 1; + MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size); + dll_name_buffer[dll_name.size] = 0; + + String8 import_data = str8(buffer, buffer_size); + return import_data; +} + +internal String8 +coff_make_import_header_by_ordinal(Arena *arena, + String8 dll_name, + COFF_MachineType machine, + COFF_TimeStamp time_stamp, + U16 ordinal, + COFF_ImportType type) +{ + COFF_ImportHeaderFlags flags = 0; + flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift; + flags |= COFF_ImportBy_Ordinal << COFF_ImportHeader_ImportByShift; + + COFF_ImportHeader header = {0}; + header.sig1 = COFF_Machine_Unknown; + header.sig2 = max_U16; + header.version = 0; + header.machine = machine; + header.time_stamp = time_stamp; + header.data_size = safe_cast_u32(dll_name.size + 2); + header.hint_or_ordinal = ordinal; + header.flags = flags; + + // alloc memory + U64 buffer_size = sizeof(header) + header.data_size; + U8 *buffer = push_array_no_zero(arena, U8, buffer_size); + + // copy header + MemoryCopyStruct(buffer, &header); + + // no function name write zero + U8 *func_name = buffer + sizeof(header); + func_name[0] = 0; + + // copy dll name + U8 *dll_name_buffer = buffer + sizeof(header) + /* name.size */ + 1; + MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size); + dll_name_buffer[dll_name.size] = 0; + + String8 import_data = str8(buffer, buffer_size); + return import_data; +} + internal U64 coff_word_size_from_machine(COFF_MachineType machine) { U64 result = 0; switch (machine) { - case COFF_MachineType_X64: result = 8; break; - case COFF_MachineType_X86: result = 4; break; + case COFF_Machine_X64: result = 8; break; + case COFF_Machine_X86: result = 4; break; } return result; } @@ -544,830 +326,37 @@ coff_default_dll_base_from_machine(COFF_MachineType machine) return dll_base; } -internal String8 -coff_make_import_lookup(Arena *arena, U16 hint, String8 name) -{ - U64 buffer_size = sizeof(hint) + (name.size + 1); - U8 *buffer = push_array(arena, U8, buffer_size); - *(U16*)buffer = hint; - MemoryCopy(buffer + sizeof(hint), name.str, name.size); - buffer[buffer_size - 1] = 0; - String8 result = str8(buffer, buffer_size); - return result; -} - -internal U32 -coff_make_ordinal_32(U16 hint) -{ - U32 ordinal = (1 << 31) | hint; - return ordinal; -} - -internal U64 -coff_make_ordinal_64(U16 hint) -{ - U64 ordinal = (1ULL << 63) | hint; - return ordinal; -} - -//////////////////////////////// - -internal String8 -coff_make_import_header_by_name(Arena *arena, - String8 dll_name, - COFF_MachineType machine, - COFF_TimeStamp time_stamp, - String8 name, - U16 hint, - COFF_ImportHeaderType type) -{ - struct { - U16 sig1; - U16 sig2; - U16 version; - COFF_MachineType machine; - COFF_TimeStamp time_stamp; - U32 sizeof_data; - U16 hint_ordinal; - U16 flags; - } import_header = { - COFF_MachineType_UNKNOWN, // sig1 - max_U16, // sig2 - 0, // version - machine, - time_stamp, - safe_cast_u32(name.size + dll_name.size + 2), // sizeof_data - 0, // hint_ordinal - 0, // flags - }; - - import_header.flags |= (U16)(type & COFF_IMPORT_HEADER_TYPE_MASK) << COFF_IMPORT_HEADER_TYPE_SHIFT; - import_header.flags |= COFF_ImportHeaderNameType_NAME << COFF_IMPORT_HEADER_NAME_TYPE_SHIFT; - import_header.hint_ordinal = hint; - - // alloc memory - U64 buffer_size = sizeof(import_header) + import_header.sizeof_data; - U8 *buffer = push_array_no_zero(arena, U8, buffer_size); - - // copy header - MemoryCopy(buffer, &import_header, sizeof(import_header)); - - // copy function name - U8 *func_name = buffer + sizeof(import_header); - MemoryCopy(func_name, name.str, name.size); - func_name[name.size] = 0; - - // copy dll name - U8 *dll_name_buffer = buffer + sizeof(import_header) + name.size + 1; - MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size); - dll_name_buffer[dll_name.size] = 0; - - String8 import_data = str8(buffer, buffer_size); - return import_data; -} - -internal String8 -coff_make_import_header_by_ordinal(Arena *arena, - String8 dll_name, - COFF_MachineType machine, - COFF_TimeStamp time_stamp, - U16 ordinal, - COFF_ImportHeaderType type) -{ - struct { - U16 sig1; - U16 sig2; - U16 version; - COFF_MachineType machine; - COFF_TimeStamp time_stamp; - U32 sizeof_data; - U16 hint_ordinal; - U16 flags; - } import_header = { - COFF_MachineType_UNKNOWN, // sig1 - max_U16, // sig2 - 0, // version - machine, - time_stamp, - safe_cast_u32(/* name.size + */ dll_name.size + 2), // sizeof_data - 0, // hint_ordinal - 0, // flags - }; - - import_header.flags |= (U16)(type & COFF_IMPORT_HEADER_TYPE_MASK) << COFF_IMPORT_HEADER_TYPE_SHIFT; - import_header.flags |= COFF_ImportHeaderNameType_ORDINAL << COFF_IMPORT_HEADER_NAME_TYPE_SHIFT; - import_header.hint_ordinal = ordinal; - - // alloc memory - U64 buffer_size = sizeof(import_header) + import_header.sizeof_data; - U8 *buffer = push_array_no_zero(arena, U8, buffer_size); - - // copy header - MemoryCopyStruct(buffer, &import_header); - - // no function name write zero - U8 *func_name = buffer + sizeof(import_header); - func_name[0] = 0; - - // copy dll name - U8 *dll_name_buffer = buffer + sizeof(import_header) + /* name.size */ + 1; - MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size); - dll_name_buffer[dll_name.size] = 0; - - String8 import_data = str8(buffer, buffer_size); - return import_data; -} - -//////////////////////////////// -//~ Resources - -internal String8 -coff_resource_string_from_str16(Arena *arena, String16 string) -{ - AssertAlways(string.size <= max_U16); - U16 size16 = (U16)string.size; - - U16 *buffer = push_array_no_zero(arena, U16, size16 + 1); - MemoryCopy(buffer + 0, &size16, sizeof(size16)); - MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0])); - - return str8_array(buffer, size16 + 1); -} - -internal String8 -coff_resource_string_from_str8(Arena *arena, String8 string) -{ - Temp scratch = scratch_begin(&arena, 1); - String16 string16 = str16_from_8(scratch.arena, string); - String8 result = coff_resource_string_from_str16(arena, string16); - scratch_end(scratch); - return result; -} - -internal String8 -coff_resource_number_from_u16(Arena *arena, U16 number) -{ - U16 *buffer = push_array_no_zero(arena, U16, 2); - buffer[0] = max_U16; - buffer[1] = number; - return str8_array(buffer, 2); -} - -internal B32 -coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b) -{ - B32 is_equal = 0; - if (a.type == b.type) { - switch (a.type) { - case COFF_ResourceIDType_NULL: break; - case COFF_ResourceIDType_NUMBER: is_equal = (a.u.number == b.u.number); break; - case COFF_ResourceIDType_STRING: is_equal = str8_match(a.u.string, b.u.string, 0); break; - default: Assert(!"invalid resource id type"); - } - } - return is_equal; -} - -internal COFF_ResourceID -coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16) -{ - COFF_ResourceID id = {0}; - id.type = id_16->type; - switch (id_16->type) { - case COFF_ResourceIDType_NULL: break; - case COFF_ResourceIDType_NUMBER: { - id.u.number = id_16->u.number; - } break; - case COFF_ResourceIDType_STRING: { - id.u.string = str8_from_16(arena, id_16->u.string); - } break; - default: InvalidPath; - } - return id; -} - -internal U64 -coff_read_resource_id_utf16(String8 data, U64 off, COFF_ResourceID_16 *id_out) -{ - U64 cursor = off; - - U16 flag = 0; - str8_deserial_read_struct(data, cursor, &flag); - - if (flag == max_U16) { - id_out->type = COFF_ResourceIDType_NUMBER; - cursor += sizeof(flag); - cursor += str8_deserial_read_struct(data, cursor, &id_out->u.number); - } else { - id_out->type = COFF_ResourceIDType_STRING; - cursor += str8_deserial_read_windows_utf16_string16(data, cursor, &id_out->u.string); - } - - U64 read_size = cursor - off; - read_size = AlignPow2(read_size, COFF_RES_ALIGN); - return read_size; -} - -internal U64 -coff_read_resource(String8 raw_res, U64 off, Arena *arena, COFF_Resource *res_out) -{ - String8 raw_header = str8_skip(raw_res, off); - U64 header_cursor = 0; - - // prefix - COFF_ResourceHeaderPrefix prefix = {0}; - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix); - - Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix)); - raw_header = str8_prefix(raw_header, prefix.header_size); - - // header - COFF_ResourceID_16 type_16 = {0}; - COFF_ResourceID_16 name_16 = {0}; - header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &type_16); - header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &name_16); - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->data_version); - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->memory_flags); - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->language_id); - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version); - header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics); - Assert(prefix.header_size == header_cursor); - - // convert utf-16 resource ids to utf-8 - res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16); - res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16); - - // read data - U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data); - Assert(prefix.data_size == data_read_size); - - // compute read size - U64 read_size = Max(prefix.header_size, sizeof(prefix)) + AlignPow2(prefix.data_size, COFF_RES_ALIGN); - return read_size; -} - -internal COFF_ResourceList -coff_resource_list_from_data(Arena *arena, String8 data) -{ - COFF_ResourceList list = {0}; - U64 cursor; - for (cursor = 0 ; cursor < data.size; ) { - COFF_ResourceNode *node = push_array(arena, COFF_ResourceNode, 1); - cursor += coff_read_resource(data, cursor, arena, &node->data); - SLLQueuePush(list.first, list.last, node); - ++list.count; - } - Assert(cursor == data.size); - return list; -} - -internal String8 -coff_write_resource_id(Arena *arena, COFF_ResourceID id) -{ - String8 result = str8_zero(); - switch (id.type) { - case COFF_ResourceIDType_NULL: break; - case COFF_ResourceIDType_NUMBER: { - result = coff_resource_number_from_u16(arena, id.u.number); - } break; - case COFF_ResourceIDType_STRING: { - result = coff_resource_string_from_str8(arena, id.u.string); - } break; - default: InvalidPath; - } - return result; -} - -internal String8 -coff_write_resource(Arena *arena, - COFF_ResourceID type, - COFF_ResourceID name, - U32 data_version, - COFF_ResourceMemoryFlags memory_flags, - U16 language_id, - U32 version, - U32 characteristics, - String8 data) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8List list = {0}; - - COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1); - String8 packed_type = coff_write_resource_id(scratch.arena, type); - String8 packed_name = coff_write_resource_id(scratch.arena, name); - - // prefix + header - str8_list_push(scratch.arena, &list, str8_struct(prefix)); - str8_list_push(scratch.arena, &list, packed_type); - str8_list_push(scratch.arena, &list, packed_name); - str8_list_push(scratch.arena, &list, str8_struct(&data_version)); - str8_list_push(scratch.arena, &list, str8_struct(&memory_flags)); - str8_list_push(scratch.arena, &list, str8_struct(&language_id)); - str8_list_push(scratch.arena, &list, str8_struct(&version)); - str8_list_push(scratch.arena, &list, str8_struct(&characteristics)); - - prefix->data_size = safe_cast_u32(data.size); - prefix->header_size = safe_cast_u32(list.total_size); - - // data - str8_list_push(scratch.arena, &list, data); - - // magic - str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic)); - - // align - U64 align_size = AlignPow2(list.total_size, COFF_RES_ALIGN) - list.total_size; - U8 *align = push_array(scratch.arena, U8, align_size); - str8_list_push(scratch.arena, &list, str8(align, align_size)); - - // join - String8 res = str8_list_join(arena, &list, 0); - - scratch_end(scratch); - return res; -} - -//////////////////////////////// - -internal COFF_DataType -coff_data_type_from_data(String8 data) -{ - B32 is_big_obj = coff_is_big_obj(data); - if (is_big_obj) { - return COFF_DataType_BIG_OBJ; - } - B32 is_import = coff_is_import(data); - if (is_import) { - return COFF_DataType_IMPORT; - } - return COFF_DataType_OBJ; -} - -internal B32 -coff_is_import(String8 data) -{ - B32 is_import = 0; - if (data.size >= sizeof(U16)*2) { - U16 *sig1 = (U16*)data.str; - U16 *sig2 = sig1 + 1; - is_import = *sig1 == COFF_MachineType_UNKNOWN && *sig2 == 0xffff; - } - return is_import; -} - -internal B32 -coff_is_archive(String8 data) -{ - B32 is_archive = 0; - U8 sig[sizeof(g_coff_archive_sig)]; - if (str8_deserial_read_struct(data, 0, &sig) == sizeof(sig)) { - is_archive = MemoryCompare(&sig[0], &g_coff_archive_sig[0], sizeof(g_coff_archive_sig)) == 0; - } - return is_archive; -} - -internal B32 -coff_is_thin_archive(String8 data) -{ - B32 is_archive = 0; - U8 sig[sizeof(g_coff_thin_archive_sig)]; - if (str8_deserial_read_struct(data, 0, &sig) == sizeof(sig)) { - is_archive = MemoryCompare(&sig[0], &g_coff_thin_archive_sig[0], sizeof(g_coff_thin_archive_sig)) == 0; - } - return is_archive; -} - -internal COFF_ArchiveType -coff_archive_type_from_data(String8 data) -{ - if (coff_is_archive(data)) { - return COFF_Archive_Regular; - } else if (coff_is_thin_archive(data)) { - return COFF_Archive_Thin; - } - return COFF_Archive_Null; -} - -internal U64 -coff_parse_archive_member_header(String8 data, U64 offset, B32 is_regular_archive, COFF_ArchiveMemberHeader *header_out) -{ - static const U64 name_size = 16; - static const U64 date_size = 12; - static const U64 user_id_size = 6; - static const U64 group_id_size = 6; - static const U64 mode_size = 8; - static const U64 size_size = 10; - static const String8 end_magic = str8_lit_comp("`\n"); - U64 total_header_size = name_size + date_size + user_id_size + group_id_size + mode_size + size_size + end_magic.size; - - U64 cursor = offset; - if (cursor + total_header_size <= data.size) { - String8 name = str8_zero(); - String8 date = str8_zero(); - String8 user_id = str8_zero(); - String8 group_id = str8_zero(); - String8 mode = str8_zero(); - String8 size = str8_zero(); - String8 end = str8_zero(); - - cursor += str8_deserial_read_block(data, cursor, name_size, &name ); - cursor += str8_deserial_read_block(data, cursor, date_size, &date ); - cursor += str8_deserial_read_block(data, cursor, user_id_size, &user_id ); - cursor += str8_deserial_read_block(data, cursor, group_id_size, &group_id); - cursor += str8_deserial_read_block(data, cursor, mode_size, &mode ); - cursor += str8_deserial_read_block(data, cursor, size_size, &size ); - cursor += str8_deserial_read_block(data, cursor, 2, &end ); - - name = str8_skip_chop_whitespace(name); - date = str8_skip_chop_whitespace(date); - user_id = str8_skip_chop_whitespace(user_id); - group_id = str8_skip_chop_whitespace(group_id); - mode = str8_skip_chop_whitespace(mode); - size = str8_skip_chop_whitespace(size); - - header_out->name = name; - header_out->time_stamp = u32_from_str8(date, 10); - header_out->user_id = u32_from_str8(user_id, 10); - header_out->group_id = u32_from_str8(group_id, 10); - header_out->mode = mode; - header_out->is_end_correct = str8_match(end, end_magic, 0); - header_out->data_range = rng_1u64(cursor, cursor + u32_from_str8(size, 10)); - - if (is_regular_archive) { - cursor = header_out->data_range.max; - } - } - - U64 result = AlignPow2((cursor - offset), COFF_ARCHIVE_ALIGN); - return result; -} - -internal B32 -coff_parse_archive_member_data(String8 data, U64 cursor, COFF_ArchiveMember *member_out) -{ - B32 is_parsed = 0; - - COFF_ArchiveMemberHeader header; header.is_end_correct = 0; - coff_parse_archive_member_header(data, cursor, 1, &header); - - if (header.is_end_correct) { - member_out->header = header; - member_out->offset = cursor; - member_out->data = str8_substr(data, header.data_range); - - cursor = AlignPow2(header.data_range.max, COFF_ARCHIVE_ALIGN); - - is_parsed = 1; - } else { - MemoryZeroStruct(&member_out->header); - member_out->offset = max_U64; - member_out->data = str8_zero(); - } - - return is_parsed; -} - -internal COFF_ArchiveFirstMember -coff_parse_first_archive_member(COFF_ArchiveMember *member) -{ - Assert(str8_match_lit("/", member->header.name, 0)); - - U64 cursor = 0; - - U32 symbol_count = 0; - cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); - - symbol_count = from_be_u32(symbol_count); - - Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U32)); - cursor += dim_1u64(member_offsets_range); - - Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); - cursor += dim_1u64(string_table_range); - - String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); - U32 *member_offsets = (U32 *)raw_member_offsets.str; - U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); - - COFF_ArchiveFirstMember result = {0}; - result.symbol_count = symbol_count; - result.member_offset_count = member_offset_count; - result.member_offsets = member_offsets; - result.string_table = str8_substr(member->data, string_table_range); - - return result; -} - -internal COFF_ArchiveSecondMember -coff_parse_second_archive_member(COFF_ArchiveMember *member) -{ - COFF_ArchiveSecondMember result = {0}; - - if (str8_match_lit("/", member->header.name, 0)) { - U64 cursor = 0; - - U32 member_count = 0; - cursor += str8_deserial_read_struct(member->data, cursor, &member_count); - - Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + member_count * sizeof(U32)); - cursor += dim_1u64(member_offsets_range); - - U32 symbol_count = 0; - cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); - - Rng1U64 symbol_indices_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U16)); - cursor += dim_1u64(symbol_indices_range); - - Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); - - String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); - String8 raw_indices = str8_substr(member->data, symbol_indices_range); - - U32 *member_offsets = (U32 *)raw_member_offsets.str; - U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); - - U16 *symbol_indices = (U16 *)raw_indices.str; - U64 symbol_index_count = raw_indices.size / sizeof(symbol_indices[0]); - - result.member_count = member_count; - result.symbol_count = symbol_count; - result.member_offsets = member_offsets; - result.member_offset_count = member_offset_count; - result.symbol_indices = symbol_indices; - result.symbol_index_count = symbol_index_count; - result.string_table = str8_substr(member->data, string_table_range); - } - - return result; -} - -internal String8 -coff_parse_long_name(String8 long_names, String8 name) -{ - String8 result = name; - if (name.size > 0 && name.str[0] == '/') { - String8 offset_str = str8(name.str + 1, name.size - 1); - U64 offset = u64_from_str8(offset_str, 10); - if (offset < long_names.size) { - U8 *ptr = long_names.str + offset; - U8 *opl = long_names.str + long_names.size; - for (; ptr < opl; ++ptr) { - if (*ptr == '\0' || *ptr == '\n') { - break; - } - } - result = str8_range(long_names.str + offset, ptr); - } - } - return result; -} - -internal U64 -coff_parse_archive_import(String8 data, U64 offset, COFF_ImportHeader *header_out) -{ - U64 cursor = offset; - - cursor += str8_deserial_read_struct(data, cursor, &header_out->sig1); - cursor += str8_deserial_read_struct(data, cursor, &header_out->sig2); - cursor += str8_deserial_read_struct(data, cursor, &header_out->version); - cursor += str8_deserial_read_struct(data, cursor, &header_out->machine); - cursor += str8_deserial_read_struct(data, cursor, &header_out->time_stamp); - cursor += str8_deserial_read_struct(data, cursor, &header_out->data_size); - cursor += str8_deserial_read_struct(data, cursor, &header_out->hint); - - U16 flags = 0; - cursor += str8_deserial_read_struct(data, cursor, &flags); - header_out->type = COFF_IMPORT_HEADER_GET_TYPE(flags); - header_out->name_type = COFF_IMPORT_HEADER_GET_NAME_TYPE(flags); - - header_out->func_name = str8_zero(); - cursor += str8_deserial_read_cstr(data, cursor, &header_out->func_name); - - header_out->dll_name = str8_zero(); - cursor += str8_deserial_read_cstr(data, cursor, &header_out->dll_name); - - Assert(header_out->func_name.size + header_out->dll_name.size + /* nulls */ 2 == header_out->data_size); - - U64 read_size = cursor - offset; - return read_size; -} - -internal COFF_ArchiveMember -coff_archive_member_from_offset(String8 data, U64 offset) -{ - COFF_ArchiveMember member = {0}; - coff_archive_member_iter_next(data, &offset, &member); - return member; -} - -internal COFF_ArchiveMember -coff_archive_member_from_data(String8 data) -{ - return coff_archive_member_from_offset(data, 0); -} - -internal COFF_ImportHeader -coff_archive_import_from_data(String8 data) -{ - COFF_ImportHeader header = {0}; - coff_parse_archive_import(data, 0, &header); - return header; -} - -internal U64 -coff_archive_member_iter_init(String8 data) -{ - U64 cursor = data.size; - if (coff_is_archive(data)) { - cursor = sizeof(g_coff_archive_sig); - } - return cursor; -} - -internal B32 -coff_archive_member_iter_next(String8 data, U64 *offset, COFF_ArchiveMember *member_out) -{ - B32 is_parsed; - - COFF_ArchiveMemberHeader header; header.is_end_correct = 0; - U64 read_size = coff_parse_archive_member_header(data, *offset, 1, &header); - - if (header.is_end_correct) { - member_out->header = header; - member_out->offset = *offset; - member_out->data = str8_substr(data, header.data_range); - - *offset += read_size; - - is_parsed = 1; - } else { - MemoryZeroStruct(&member_out->header); - member_out->offset = max_U64; - member_out->data = str8(0,0); - - is_parsed = 0; - } - - return is_parsed; -} - -internal U64 -coff_thin_archive_member_iter_init(String8 data) -{ - U64 cursor = data.size; - if (coff_is_thin_archive(data)) { - cursor = sizeof(g_coff_thin_archive_sig); - } - return cursor; -} - -internal B32 -coff_thin_archive_member_iter_next(String8 data, U64 *offset, COFF_ArchiveMember *member_out) -{ - B32 is_parsed = 0; - - member_out->header.is_end_correct = 0; - U64 header_size = coff_parse_archive_member_header(data, *offset, 0, &member_out->header); - - if (member_out->header.is_end_correct) { - member_out->offset = *offset; - if (str8_match_lit("/", member_out->header.name, 0) || str8_match_lit("//", member_out->header.name, 0)) { - member_out->data = str8_substr(data, member_out->header.data_range); - } else { - // size field in non-header members means size of stand-alone obj - member_out->data = str8_zero(); - } - *offset += header_size; - is_parsed = 1; - } - - return is_parsed; -} - -internal void -coff_archive_member_list_push_node(COFF_ArchiveMemberList *list, COFF_ArchiveMemberNode *node) -{ - SLLQueuePush(list->first, list->last, node); - list->count += 1; -} - -internal COFF_ArchiveParse -coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) -{ - String8 error = str8_zero(); - B32 has_second_header = 0; - B32 has_long_names = 0; - COFF_ArchiveMember first_header = {0}; - COFF_ArchiveMember second_header = {0}; - COFF_ArchiveMember long_names_member = {0}; - - COFF_ArchiveMemberNode *ptr = member_list.first; - - if (ptr) { - if (str8_match_lit("/", ptr->data.header.name, 0)) { - if (ptr->data.header.is_end_correct) { - first_header = ptr->data; - ptr = ptr->next; - } else { - error = str8_lit("first header doesn't have correct end"); - } - } - } else { - error = str8_lit("missing first header"); - } - - if (!error.size && ptr) { - if (str8_match_lit("/", ptr->data.header.name, 0)) { - if (ptr->data.header.is_end_correct) { - second_header = ptr->data; - ptr = ptr->next; - has_second_header = 1; - } else { - error = str8_lit("second header doesn't have correct end"); - } - } - } - - if (!error.size && ptr) { - if (str8_match_lit("//", ptr->data.header.name, 0)) { - if (ptr->data.header.is_end_correct) { - long_names_member = ptr->data; - ptr = ptr->next; - has_long_names; - } else { - error = str8_lit("long names header doesn't have correct end"); - } - } - } - - COFF_ArchiveParse parse = {0}; - parse.has_second_header = has_second_header; - parse.has_long_names = has_long_names; - parse.first_member = coff_parse_first_archive_member(&first_header); - parse.second_member = coff_parse_second_archive_member(&second_header); - parse.long_names = long_names_member.data; - parse.error = error; - - return parse; -} - -internal COFF_ArchiveParse -coff_archive_from_data(String8 data) -{ - COFF_ArchiveMemberList list = {0}; - COFF_ArchiveMemberNode node_arr[3] = {0}; - U64 cursor = coff_archive_member_iter_init(data); - for (U64 i = 0; i < ArrayCount(node_arr); ++i) { - COFF_ArchiveMemberNode *node = &node_arr[i]; - if (!coff_archive_member_iter_next(data, &cursor, &node->data)) { - break; - } - coff_archive_member_list_push_node(&list, node); - } - return coff_archive_parse_from_member_list(list); -} - -internal COFF_ArchiveParse -coff_thin_archive_from_data(String8 data) -{ - COFF_ArchiveMemberList list = {0}; - COFF_ArchiveMemberNode node_arr[3] = {0}; - U64 cursor = coff_thin_archive_member_iter_init(data); - for (U64 i = 0; i < ArrayCount(node_arr); i += 1) { - COFF_ArchiveMemberNode *node = &node_arr[i]; - if (!coff_thin_archive_member_iter_next(data, &cursor, &node->data)) { - break; - } - coff_archive_member_list_push_node(&list, node); - } - return coff_archive_parse_from_member_list(list); -} - -internal COFF_ArchiveParse -coff_archive_parse_from_data(String8 data) -{ - COFF_ArchiveType type = coff_archive_type_from_data(data); - switch (type) { - case COFF_Archive_Null: break; - case COFF_Archive_Regular: return coff_archive_from_data(data); - case COFF_Archive_Thin: return coff_thin_archive_from_data(data); - } - COFF_ArchiveParse null_parse = {0}; - return null_parse; -} internal Arch arch_from_coff_machine(COFF_MachineType machine) { Arch result = Arch_Null; switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: result = Arch_x86; break; - case COFF_MachineType_X64: result = Arch_x64; break; - case COFF_MachineType_ARM: result = Arch_arm32; break; - case COFF_MachineType_ARM64: result = Arch_arm64; break; + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: result = Arch_x86; break; + case COFF_Machine_X64: result = Arch_x64; break; + case COFF_Machine_Arm: result = Arch_arm32; break; + case COFF_Machine_Arm64: result = Arch_arm64; break; } return result; } +internal U64 +coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff) +{ + U64 foff = 0; + for(U64 sect_idx = 0; sect_idx < section_count; sect_idx += 1) + { + COFF_SectionHeader *sect = §ions[sect_idx]; + if(sect->voff <= voff && voff < sect->voff+sect->vsize) + { + if(!(sect->flags & COFF_SectionFlag_CntUninitializedData)) + { + foff = sect->foff + (voff - sect->voff); + } + break; + } + } + return foff; +} + diff --git a/src/coff/coff.h b/src/coff/coff.h index 6ec8c8f6..97727aef 100644 --- a/src/coff/coff.h +++ b/src/coff/coff.h @@ -4,434 +4,258 @@ #ifndef COFF_H #define COFF_H +//////////////////////////////// +//~ rjf: COFF Format Types + +read_only global U8 g_coff_big_header_magic[] = +{ + 0xc7, 0xa1, 0xba, 0xd1, 0xee, 0xba, 0xa9, 0x4b, 0xaf, 0x20, 0xfa, 0xf6, 0x6a, 0xa4, 0xdc, 0xb8 +}; +read_only global U8 g_coff_res_magic[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +read_only global U8 g_coff_archive_sig[8] = "!\n"; +read_only global U8 g_coff_thin_archive_sig[8] = "!\n"; + +#pragma pack(push, 1) + typedef U32 COFF_TimeStamp; -//////////////////////////////// -//~ rjf: Coff Format Types - -#pragma pack(push,1) - -typedef U16 COFF_Flags; +typedef U16 COFF_FileHeaderFlags; 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), + COFF_FileHeaderFlag_RelocStripped = (1 << 0), + COFF_FileHeaderFlag_ExecutableImage = (1 << 1), + COFF_FileHeaderFlag_LineNumbersStripped = (1 << 2), + COFF_FileHeaderFlag_SymbolsStripped = (1 << 3), + COFF_FileHeaderFlag_Reserved0 = (1 << 4), + COFF_FileHeaderFlag_LargeAddressAware = (1 << 5), + COFF_FileHeaderFlag_Reserved1 = (1 << 6), + COFF_FileHeaderFlag_Reserved2 = (1 << 7), + COFF_FileHeaderFlag_32BitMachine = (1 << 8), + COFF_FileHeaderFlag_DebugStripped = (1 << 9), + COFF_FileHeaderFlag_RemovableRunFromSwap = (1 << 10), + COFF_FileHeaderFlag_NetRunFromSwap = (1 << 11), + COFF_FileHeaderFlag_System = (1 << 12), + COFF_FileHeaderFlag_Dll = (1 << 13), + COFF_FileHeaderFlag_UpSystemOnly = (1 << 14), + COFF_FileHeaderFlag_BytesReservedHi = (1 << 15) }; typedef U16 COFF_MachineType; enum { - COFF_MachineType_UNKNOWN = 0x0, - COFF_MachineType_X86 = 0x14c, - COFF_MachineType_X64 = 0x8664, - COFF_MachineType_AM33 = 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 + COFF_Machine_Unknown = 0x0, + COFF_Machine_X86 = 0x14c, + COFF_Machine_X64 = 0x8664, + COFF_Machine_Am33 = 0x1d3, + COFF_Machine_Arm = 0x1c0, + COFF_Machine_Arm64 = 0xaa64, + COFF_Machine_ArmNt = 0x1c4, + COFF_Machine_Ebc = 0xebc, + COFF_Machine_Ia64 = 0x200, + COFF_Machine_M32R = 0x9041, + COFF_Machine_Mips16 = 0x266, + COFF_Machine_MipsFpu = 0x366, + COFF_Machine_MipsFpu16 = 0x466, + COFF_Machine_PowerPc = 0x1f0, + COFF_Machine_PowerPcFp = 0x1f1, + COFF_Machine_R4000 = 0x166, + COFF_Machine_RiscV32 = 0x5032, + COFF_Machine_RiscV64 = 0x5064, + COFF_Machine_RiscV128 = 0x5128, + COFF_Machine_Sh3 = 0x1a2, + COFF_Machine_Sh3Dsp = 0x1a3, + COFF_Machine_Sh4 = 0x1a6, + COFF_Machine_Sh5 = 0x1a8, + COFF_Machine_Thumb = 0x1c2, + COFF_Machine_WceMipsV2 = 0x169 }; -typedef struct COFF_Header COFF_Header; -struct COFF_Header +typedef struct COFF_FileHeader { + COFF_MachineType machine; + U16 section_count; + COFF_TimeStamp time_stamp; + U32 symbol_table_foff; + U32 symbol_count; + U16 optional_header_size; + COFF_FileHeaderFlags flags; +} COFF_FileHeader; + +typedef struct COFF_BigObjHeader +{ + U16 sig1; // COFF_Machine_Unknown + U16 sig2; // max_U16 + U16 version; // 2 COFF_MachineType machine; - U16 section_count; COFF_TimeStamp time_stamp; + U8 magic[16]; // g_coff_big_header_magic + U8 unused[16]; + U32 section_count; U32 symbol_table_foff; U32 symbol_count; - U16 optional_header_size; - COFF_Flags flags; -}; +} COFF_BigObjHeader; 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 + 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 }; 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), + COFF_SectionFlag_TypeNoPad = (1 << 3), + COFF_SectionFlag_CntCode = (1 << 5), + COFF_SectionFlag_CntInitializedData = (1 << 6), + COFF_SectionFlag_CntUninitializedData = (1 << 7), + COFF_SectionFlag_LnkOther = (1 << 8), + COFF_SectionFlag_LnkInfo = (1 << 9), + COFF_SectionFlag_LnkRemove = (1 << 11), + COFF_SectionFlag_LnkCOMDAT = (1 << 12), + COFF_SectionFlag_GpRel = (1 << 15), + COFF_SectionFlag_Mem16Bit = (1 << 17), + COFF_SectionFlag_MemLocked = (1 << 18), + COFF_SectionFlag_MemPreload = (1 << 19), + COFF_SectionFlag_AlignShift = 20, + COFF_SectionFlag_AlignMask = 0xf, + COFF_SectionFlag_LnkNRelocOvfl = (1 << 24), + COFF_SectionFlag_MemDiscardable = (1 << 25), + COFF_SectionFlag_MemNotCached = (1 << 26), + COFF_SectionFlag_MemNotPaged = (1 << 27), + COFF_SectionFlag_MemShared = (1 << 28), + COFF_SectionFlag_MemExecute = (1 << 29), + COFF_SectionFlag_MemRead = (1 << 30), + COFF_SectionFlag_MemWrite = (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) +#define COFF_SectionFlags_ExtractAlign(f) (COFF_SectionAlign)(((f) >> COFF_SectionFlag_AlignShift) & COFF_SectionFlag_AlignMask) +#define COFF_SectionFlags_LnkFlags ((COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift) | COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkOther | COFF_SectionFlag_LnkRemove | COFF_SectionFlag_LnkNRelocOvfl) -typedef struct COFF_SectionHeader COFF_SectionHeader; -struct COFF_SectionHeader +typedef 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; + 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; -}; +} COFF_SectionHeader; -typedef U16 COFF_RelocType; - -typedef COFF_RelocType 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 COFF_RelocType 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 COFF_RelocType 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 COFF_RelocType 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 + 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_MemberOfEnumeration, + COFF_SymType_Byte, + COFF_SymType_Word, + COFF_SymType_UInt, + COFF_SymType_DWord }; 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 + COFF_SymStorageClass_Null = 0x00, + COFF_SymStorageClass_Automatic = 0x01, + COFF_SymStorageClass_External = 0x02, + COFF_SymStorageClass_Static = 0x03, + COFF_SymStorageClass_Register = 0x04, + COFF_SymStorageClass_ExternalDef = 0x05, + COFF_SymStorageClass_Label = 0x06, + COFF_SymStorageClass_UndefinedLabel = 0x07, + COFF_SymStorageClass_MemberOfStruct = 0x08, + COFF_SymStorageClass_Argument = 0x09, + COFF_SymStorageClass_StructTag = 0x0a, + COFF_SymStorageClass_MemberOfUnion = 0x0b, + COFF_SymStorageClass_UnionTag = 0x0c, + COFF_SymStorageClass_TypeDefinition = 0x0d, + COFF_SymStorageClass_UndefinedStatic = 0x0e, + COFF_SymStorageClass_EnumTag = 0x0f, + COFF_SymStorageClass_MemberOfEnum = 0x10, + COFF_SymStorageClass_RegisterParam = 0x11, + COFF_SymStorageClass_BitField = 0x12, + COFF_SymStorageClass_Block = 0x64, + COFF_SymStorageClass_Function = 0x65, + COFF_SymStorageClass_EndOfStruct = 0x66, + COFF_SymStorageClass_File = 0x67, + COFF_SymStorageClass_Section = 0x68, + COFF_SymStorageClass_WeakExternal = 0x69, + COFF_SymStorageClass_CLRToken = 0x6b, + COFF_SymStorageClass_EndOfFunction = 0xff }; 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 - -typedef struct COFF_HeaderBigObj COFF_HeaderBigObj; -struct COFF_HeaderBigObj -{ - U16 sig1; // COFF_MachineType_UNKNOWN - U16 sig2; // U16_MAX - U16 version; // COFF_MIN_BIG_OBJ_VERSION - COFF_MachineType machine; - COFF_TimeStamp time_stamp; - U8 magic[16]; - U32 unused[4]; - U32 section_count; - U32 symbol_table_foff; - U32 symbol_count; + COFF_SymDType_Null = 0x00, + COFF_SymDType_Ptr = 0x10, + COFF_SymDType_Func = 0x20, + COFF_SymDType_Array = 0x30 }; // 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) +#define COFF_Symbol_UndefinedSection 0 +#define COFF_Symbol_AbsSection32 ((U32)-1) +#define COFF_Symbol_DebugSection32 ((U32)-2) +#define COFF_Symbol_AbsSection16 ((U16)-1) +#define COFF_Symbol_DebugSection16 ((U16)-2) -typedef union COFF_SymbolName COFF_SymbolName; -union COFF_SymbolName +typedef union COFF_SymbolName { U8 short_name[8]; - struct - { + struct { // if this field is filled with zeroes we have a long name, - // which means name is stored in the string table + // 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; -}; +} COFF_SymbolName; -#define COFF_SymbolType_IsFunc(x) ((x).u.lsb == COFF_SymType_NULL && (x).u.msb == COFF_SymDType_FUNC) +#define COFF_SymbolType_IsFunc(x) ((x).u.lsb == COFF_SymType_Null && (x).u.msb == COFF_SymDType_Func) -typedef union COFF_SymbolType COFF_SymbolType; -union COFF_SymbolType +typedef union COFF_SymbolType { - struct - { + struct { COFF_SymDType msb; - COFF_SymType lsb; + COFF_SymType lsb; } u; U16 v; -}; +} COFF_SymbolType; -typedef struct COFF_Symbol16 COFF_Symbol16; -struct COFF_Symbol16 +typedef struct COFF_Symbol16 { COFF_SymbolName name; U32 value; @@ -439,10 +263,9 @@ struct COFF_Symbol16 COFF_SymbolType type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; -}; +} COFF_Symbol16; -typedef struct COFF_Symbol32 COFF_Symbol32; -struct COFF_Symbol32 +typedef struct COFF_Symbol32 { COFF_SymbolName name; U32 value; @@ -450,12 +273,20 @@ struct COFF_Symbol32 COFF_SymbolType type; COFF_SymStorageClass storage_class; U8 aux_symbol_count; -}; +} COFF_Symbol32; // 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 +#define COFF_AuxSymbolSize 18 -// storage class: EXTERNAL +typedef U32 COFF_WeakExtType; +enum +{ + COFF_WeakExt_NoLibrary = 1, + COFF_WeakExt_SearchLibrary = 2, + COFF_WeakExt_SearchAlias = 3 +}; + +// storage class: External typedef struct COFF_SymbolFuncDef { U32 tag_index; @@ -465,7 +296,7 @@ typedef struct COFF_SymbolFuncDef U8 unused[2]; } COFF_SymbolFuncDef; -// storage class: FUNCTION +// storage class: Function typedef struct COFF_SymbolFunc { U8 unused[4]; @@ -475,7 +306,7 @@ typedef struct COFF_SymbolFunc U8 unused3[2]; } COFF_SymbolFunc; -// storage class: WEAK_EXTERNAL +// storage class: WeakExternal typedef struct COFF_SymbolWeakExt { U32 tag_index; @@ -483,39 +314,145 @@ typedef struct COFF_SymbolWeakExt U8 unused[10]; } COFF_SymbolWeakExt; -typedef struct COFF_SymbolFile +typedef struct COFF_SymbolFile { - char name[18]; + U8 name[18]; } COFF_SymbolFile; +typedef U8 COFF_ComdatSelectType; +enum +{ + COFF_ComdatSelect_Null = 0, + COFF_ComdatSelect_NoDuplicates = 1, // Only one symbol is allowed to be in global symbol table, otherwise multiply defintion error is thrown. + COFF_ComdatSelect_Any = 2, // Select any symbol, even if there are multiple definitions. (we default to first declaration) + COFF_ComdatSelect_SameSize = 3, // Sections that symbols reference must match in size, otherwise multiply definition error is thrown. + COFF_ComdatSelect_ExactMatch = 4, // Sections that symbols reference must have identical checksums, otherwise multiply defintion error is thrown. + COFF_ComdatSelect_Associative = 5, // Symbols with associative type form a chain of sections are related to each other. (next link is indicated in COFF_SecDef in 'number') + COFF_ComdatSelect_Largest = 6 // Linker selects section with largest size. +}; + // provides information about section to which symbol refers to. -// storage class: STATIC +// storage class: Static typedef struct COFF_SymbolSecDef { U32 length; U16 number_of_relocations; U16 number_of_ln; U32 check_sum; - U16 number_lo; // low 16 bits of one-based section index + U16 number_lo; // low 16 bits of one-based section index COFF_ComdatSelectType selection; U8 unused; U16 number_hi; } COFF_SymbolSecDef; -// specifies how section data should be modified when placed in the image file. -typedef struct COFF_Reloc COFF_Reloc; -struct COFF_Reloc +//////////////////////////////// + +typedef U16 COFF_RelocType; + +typedef COFF_RelocType COFF_Reloc_X64; +enum { - 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 + COFF_Reloc_X64_Abs = 0x0, + COFF_Reloc_X64_Addr64 = 0x1, + COFF_Reloc_X64_Addr32 = 0x2, + COFF_Reloc_X64_Addr32Nb = 0x3, // NB => No Base + COFF_Reloc_X64_Rel32 = 0x4, + COFF_Reloc_X64_Rel32_1 = 0x5, + COFF_Reloc_X64_Rel32_2 = 0x6, + COFF_Reloc_X64_Rel32_3 = 0x7, + COFF_Reloc_X64_Rel32_4 = 0x8, + COFF_Reloc_X64_Rel32_5 = 0x9, + COFF_Reloc_X64_Section = 0xA, + COFF_Reloc_X64_SecRel = 0xB, + COFF_Reloc_X64_SecRel7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token + COFF_Reloc_X64_Token = 0xD, + COFF_Reloc_X64_SRel32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR + COFF_Reloc_X64_Pair = 0xF, + COFF_Reloc_X64_SSpan32 = 0x10 }; -#pragma pack(pop) +typedef COFF_RelocType COFF_Reloc_X86; +enum +{ + COFF_Reloc_X86_Abs = 0x0, // relocation is ignored + COFF_Reloc_X86_Dir16 = 0x1, // no support + COFF_Reloc_X86_Rel16 = 0x2, // no support + COFF_Reloc_X86_Unknown0 = 0x3, + COFF_Reloc_X86_Unknown2 = 0x4, + COFF_Reloc_X86_Unknown3 = 0x5, + COFF_Reloc_X86_Dir32 = 0x6, // 32-bit virtual address + COFF_Reloc_X86_Dir32Nb = 0x7, // 32-bit virtual offset + COFF_Reloc_X86_Seg12 = 0x9, // no support + COFF_Reloc_X86_Section = 0xa, // 16-bit section index, used for debug info purposes + COFF_Reloc_X86_SecRel = 0xb, // 32-bit offset from start of a section + COFF_Reloc_X86_Token = 0xc, // CLR token? (for managed languages) + COFF_Reloc_X86_SecRel7 = 0xd, // 7-bit offset from the base of the section that contains the target. + COFF_Reloc_X86_Unknown4 = 0xe, + COFF_Reloc_X86_Unknown5 = 0xf, + COFF_Reloc_X86_Unknown6 = 0x10, + COFF_Reloc_X86_Unknown7 = 0x11, + COFF_Reloc_X86_Unknown8 = 0x12, + COFF_Reloc_X86_Unknown9 = 0x13, + COFF_Reloc_X86_Rel32 = 0x14 +}; + +typedef COFF_RelocType COFF_Reloc_Arm; +enum +{ + COFF_Reloc_Arm_Abs = 0x0, + COFF_Reloc_Arm_Addr32 = 0x1, + COFF_Reloc_Arm_Addr32Nb = 0x2, + COFF_Reloc_Arm_Branch24 = 0x3, + COFF_Reloc_Arm_Branch11 = 0x4, + COFF_Reloc_Arm_Unknown1 = 0x5, + COFF_Reloc_Arm_Unknown2 = 0x6, + COFF_Reloc_Arm_Unknown3 = 0x7, + COFF_Reloc_Arm_Unknown4 = 0x8, + COFF_Reloc_Arm_Unknown5 = 0x9, + COFF_Reloc_Arm_Rel32 = 0xa, + COFF_Reloc_Arm_Section = 0xe, + COFF_Reloc_Arm_SecRel = 0xf, + COFF_Reloc_Arm_Mov32 = 0x10, + COFF_Reloc_Arm_ThumbMov32 = 0x11, + COFF_Reloc_Arm_ThumbBranch20 = 0x12, + COFF_Reloc_Arm_Unused = 0x13, + COFF_Reloc_Arm_ThumbBranch24 = 0x14, + COFF_Reloc_Arm_ThumbBlx23 = 0x15, + COFF_Reloc_Arm_Pair = 0x16 +}; + +typedef COFF_RelocType COFF_Reloc_Arm64; +enum +{ + COFF_Reloc_Arm64_Abs = 0x0, + COFF_Reloc_Arm64_Addr32 = 0x1, + COFF_Reloc_Arm64_Addr32Nb = 0x2, + COFF_Reloc_Arm64_Branch26 = 0x3, + COFF_Reloc_Arm64_PageBaseRel21 = 0x4, + COFF_Reloc_Arm64_Rel21 = 0x5, + COFF_Reloc_Arm64_PageOffset12a = 0x6, + COFF_Reloc_Arm64_SecRel = 0x8, + COFF_Reloc_Arm64_SecRelLow12a = 0x9, + COFF_Reloc_Arm64_SecRelHigh12a = 0xa, + COFF_Reloc_Arm64_SecRelLow12l = 0xb, + COFF_Reloc_Arm64_Token = 0xc, + COFF_Reloc_Arm64_Section = 0xd, + COFF_Reloc_Arm64_Addr64 = 0xe, + COFF_Reloc_Arm64_Branch19 = 0xf, + COFF_Reloc_Arm64_Branch14 = 0x10, + COFF_Reloc_Arm64_Rel32 = 0x11 +}; + +typedef struct COFF_Reloc +{ + U32 apply_off; // section relative offset where relocation is placed + U32 isymbol; // zero based index into coff symbol table + COFF_RelocType type; // relocation type that depends on the arch +} COFF_Reloc; //////////////////////////////// -#define COFF_RES_ALIGN 4u +#define COFF_ResourceAlign 4u typedef struct COFF_ResourceHeaderPrefix { @@ -526,52 +463,12 @@ typedef struct COFF_ResourceHeaderPrefix typedef U16 COFF_ResourceMemoryFlags; enum { - COFF_ResourceMemoryFlag_MOVEABLE = 0x10, - COFF_ResourceMemoryFlag_PURE = 0x20, - COFF_ResourceMemoryFlag_PRELOAD = 0x40, - COFF_ResourceMemoryFlag_DISCARDABLE = 0x1000, + 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; - U32 data_version; - COFF_ResourceMemoryFlags memory_flags; - U16 language_id; - U32 version; - U32 characteristics; - String8 data; -} COFF_Resource; - typedef struct COFF_ResourceDataEntry { U32 data_voff; @@ -590,7 +487,7 @@ typedef struct COFF_ResourceDirTable U16 id_entry_count; } COFF_ResourceDirTable; -#define COFF_RESOURCE_SUB_DIR_FLAG (1u << 31u) +#define COFF_Resource_SubDirFlag (1u << 31u) typedef struct COFF_ResourceDirEntry { union { @@ -605,311 +502,103 @@ typedef struct COFF_ResourceDirEntry //////////////////////////////// -#define COFF_ARCHIVE_ALIGN 2 -#define COFF_ARCHIVE_MAX_SHORT_NAME_SIZE 15 -#define COFF_ARCHIVE_MEMBER_HEADER_SIZE 60 +#define COFF_Archive_MemberAlign 2 +#define COFF_Archive_MaxShortNameSize 15 typedef struct COFF_ArchiveMemberHeader { - String8 name; // padded to 16 bytes with spaces - COFF_TimeStamp time_stamp; - 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 - B32 is_end_correct; // set to true if found correct signature after header - Rng1U64 data_range; + U8 name[16]; + U8 date[12]; + U8 user_id[6]; + U8 group_id[6]; + U8 mode[8]; + U8 size[10]; + U8 end[2]; } COFF_ArchiveMemberHeader; -//////////////////////////////// -// Helpers - +#define COFF_ImportType_Invalid max_U16 +typedef U16 COFF_ImportType; enum { - COFF_DataType_NULL, - COFF_DataType_BIG_OBJ, - COFF_DataType_OBJ, - COFF_DataType_IMPORT, + COFF_ImportHeader_Code = 0, + COFF_ImportHeader_Data = 1, + COFF_ImportHeader_Const = 2 }; -typedef U32 COFF_DataType; - -typedef struct COFF_HeaderInfo -{ - COFF_DataType type; - COFF_MachineType machine; - U64 header_size; - U64 section_array_off; - U64 section_count_no_null; - U64 string_table_off; - U64 symbol_size; - U64 symbol_off; - U64 symbol_count; -} COFF_HeaderInfo; +typedef U32 COFF_ImportByType; enum { - COFF_SymbolValueInterp_REGULAR, // symbol has section and offset. - COFF_SymbolValueInterp_WEAK, // symbol is overridable - COFF_SymbolValueInterp_UNDEFINED, // symbol doesn't have a reference section. - COFF_SymbolValueInterp_COMMON, // symbol has no section but still has size. - COFF_SymbolValueInterp_ABS, // symbol has an absolute (non-relocatable) value and is not an address. - COFF_SymbolValueInterp_DEBUG // symbol is used to provide general type of debugging information. -}; -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; - U64 member_offset_count; - U32 *member_offsets; - String8 string_table; -} COFF_ArchiveFirstMember; - -typedef struct COFF_ArchiveSecondMember -{ - U32 member_count; - U32 symbol_count; - U64 member_offset_count; - U32 *member_offsets; - U64 symbol_index_count; - U16 *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 -{ - B32 has_second_header; - B32 has_long_names; - COFF_ArchiveFirstMember first_member; - COFF_ArchiveSecondMember second_member; - String8 long_names; - String8 error; -} COFF_ArchiveParse; - -//////////////////////////////// - -typedef struct COFF_SectionHeaderArray -{ - U64 count; - COFF_SectionHeader *v; -} COFF_SectionHeaderArray; - -//////////////////////////////// - -typedef struct COFF_ParsedSymbol -{ - String8 name; - U32 value; - U32 section_number; - COFF_SymbolType type; - COFF_SymStorageClass storage_class; - U8 aux_symbol_count; -} COFF_ParsedSymbol; - -//////////////////////////////// -//~ rjf: Globals - -read_only global U8 coff_big_obj_magic[] = -{ - 0xC7,0xA1,0xBA,0xD1,0xEE,0xBA,0xA9,0x4B, - 0xAF,0x20,0xFA,0xF6,0x6A,0xA4,0xDC,0xB8, + COFF_ImportBy_Ordinal = 0, + COFF_ImportBy_Name = 1, + COFF_ImportBy_NameNoPrefix = 2, + COFF_ImportBy_Undecorate = 3 }; -read_only global U8 g_coff_archive_sig[8] = "!\n"; -read_only global U8 g_coff_thin_archive_sig[8] = "!\n"; - -read_only global U8 g_coff_res_magic[] = +typedef U16 COFF_ImportHeaderFlags; +enum { - 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + COFF_ImportHeader_TypeShift = 0, + COFF_ImportHeader_TypeMask = 3, + COFF_ImportHeader_ImportByShift = 2, + COFF_ImportHeader_ImportByMask = 3, }; +#define COFF_ImportHeader_ExtractType(x) (((x) >> COFF_ImportHeader_TypeShift ) & COFF_ImportHeader_TypeMask ) +#define COFF_ImportHeader_ExtractImportBy(x) (((x) >> COFF_ImportHeader_ImportByShift) & COFF_ImportHeader_ImportByMask) -read_only global COFF_SectionHeader coff_section_header_nil = {0}; +typedef struct COFF_ImportHeader +{ + U16 sig1; // COFF_Machine_Unknown + U16 sig2; // max_U16 + U16 version; // 0 + COFF_MachineType machine; + COFF_TimeStamp time_stamp; + U32 data_size; + U16 hint_or_ordinal; + COFF_ImportHeaderFlags flags; + // char *func_name; + // char *dll_name; +} COFF_ImportHeader; + +#pragma pack(pop) //////////////////////////////// -//~ rjf: Helper Functions +// Section -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_SectionFlags coff_section_flag_from_align_size(U64 align); -internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class); +internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags); +internal COFF_SectionFlags coff_section_flag_from_align_size (U64 align); -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_name_from_section_header(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_name_from_section_header(String8 raw_coff, COFF_SectionHeader *header, U64 string_table_off); +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 COFF_ParsedSymbol coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32); -internal COFF_ParsedSymbol coff_parse_symbol16(String8 raw_coff, U64 string_table_off, COFF_Symbol16 *sym16); -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); +//////////////////////////////// +// Symbol -internal U64 coff_apply_size_from_reloc_x64(COFF_RelocTypeX64 x); -internal U64 coff_apply_size_from_reloc_x86(COFF_RelocTypeX86 x); -internal U64 coff_apply_size_from_reloc(COFF_MachineType machine, COFF_RelocType x); +internal String8 coff_read_symbol_name(String8 raw_coff, U64 string_table_off, COFF_SymbolName *name); -internal U64 coff_word_size_from_machine(COFF_MachineType machine); +//////////////////////////////// +// Reloc + +internal U64 coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x); +internal U64 coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x); + +//////////////////////////////// +// Import + +internal U32 coff_make_ordinal32(U16 hint); +internal U64 coff_make_ordinal64(U16 hint); + +internal String8 coff_make_import_lookup (Arena *arena, U16 hint, String8 name); +internal String8 coff_make_import_header_by_name (Arena *arena, String8 dll_name, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 name, U16 hint, COFF_ImportType type); +internal String8 coff_make_import_header_by_ordinal(Arena *arena, String8 dll_name, COFF_MachineType machine, COFF_TimeStamp time_stamp, U16 ordinal, COFF_ImportType type); + +//////////////////////////////// +// Misc + +internal U64 coff_word_size_from_machine (COFF_MachineType machine); internal U64 coff_default_exe_base_from_machine(COFF_MachineType machine); internal U64 coff_default_dll_base_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 String8 coff_make_import_header_by_name(Arena *arena, - String8 dll_name, - COFF_MachineType machine, - COFF_TimeStamp time_stamp, - String8 name, - U16 hint, - COFF_ImportHeaderType type); -internal String8 coff_make_import_header_by_ordinal(Arena *arena, - String8 dll_name, - COFF_MachineType machine, - COFF_TimeStamp time_stamp, - U16 ordinal, - COFF_ImportHeaderType type); - -//////////////////////////////// -//~ Resources - -internal String8 coff_resource_string_from_str16(Arena *arena, String16 string); -internal String8 coff_resource_string_from_str8(Arena *arena, String8 string); -internal String8 coff_resource_number_from_u16(Arena *arena, U16 number); - -internal B32 coff_resource_id_is_equal(COFF_ResourceID a, COFF_ResourceID b); -internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID_16 *id_16); - -internal U64 coff_read_resource_id_utf16(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 String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id); -internal String8 coff_write_resource(Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data); - -//////////////////////////////// -//~ Archive - -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 COFF_ArchiveType coff_archive_type_from_data(String8 data); - -internal U64 coff_parse_archive_member_header(String8 data, U64 offset, B32 is_regular_archive, COFF_ArchiveMemberHeader *header_out); -internal B32 coff_parse_archive_member_data(String8 data, U64 cursor, COFF_ArchiveMember *member_out); -internal COFF_ArchiveFirstMember coff_parse_first_archive_member(COFF_ArchiveMember *member); -internal COFF_ArchiveSecondMember coff_parse_second_archive_member(COFF_ArchiveMember *member); -internal String8 coff_parse_long_name(String8 long_names, String8 name); -internal U64 coff_parse_archive_import(String8 data, U64 offset, COFF_ImportHeader *header_out); - -internal COFF_ArchiveMember coff_archive_member_from_offset(String8 data, U64 offset); -internal COFF_ArchiveMember coff_archive_member_from_data(String8 data); -internal COFF_ImportHeader coff_archive_import_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 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_archive_parse_from_member_list(COFF_ArchiveMemberList list); -internal COFF_ArchiveParse coff_archive_from_data(String8 data); -internal COFF_ArchiveParse coff_thin_archive_from_data(String8 data); -internal COFF_ArchiveParse coff_archive_parse_from_data(String8 data); - internal Arch arch_from_coff_machine(COFF_MachineType machine); +internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff); -#endif //COFF_H +#endif // COFF_H diff --git a/src/coff/coff_enum.c b/src/coff/coff_enum.c index 0830f2aa..9a8c2874 100644 --- a/src/coff/coff_enum.c +++ b/src/coff/coff_enum.c @@ -21,54 +21,54 @@ read_only struct String8 string; COFF_MachineType machine; } g_coff_machine_map[] = { - { str8_lit_comp(""), COFF_MachineType_UNKNOWN }, - { str8_lit_comp("X86"), COFF_MachineType_X86 }, - { str8_lit_comp("AMD64"), COFF_MachineType_X64 }, - { str8_lit_comp("X64"), COFF_MachineType_X64 }, - { str8_lit_comp("AM33"), COFF_MachineType_AM33 }, - { str8_lit_comp("ARM"), COFF_MachineType_ARM }, - { str8_lit_comp("ARM64"), COFF_MachineType_ARM64 }, - { str8_lit_comp("ARMNT"), COFF_MachineType_ARMNT }, - { str8_lit_comp("EBC"), COFF_MachineType_EBC }, - { str8_lit_comp("IA64"), COFF_MachineType_IA64 }, - { str8_lit_comp("M32R"), COFF_MachineType_M32R }, - { str8_lit_comp("MIPS16"), COFF_MachineType_MIPS16 }, - { str8_lit_comp("MIPSFPU"), COFF_MachineType_MIPSFPU }, - { str8_lit_comp("MIPSFPU16"), COFF_MachineType_MIPSFPU16 }, - { str8_lit_comp("POWERPC"), COFF_MachineType_POWERPC }, - { str8_lit_comp("POWERPCFP"), COFF_MachineType_POWERPCFP }, - { str8_lit_comp("R4000"), COFF_MachineType_R4000 }, - { str8_lit_comp("RISCV32"), COFF_MachineType_RISCV32 }, - { str8_lit_comp("RISCV64"), COFF_MachineType_RISCV64 }, - { str8_lit_comp("SH3"), COFF_MachineType_SH3 }, - { str8_lit_comp("SH3DSP"), COFF_MachineType_SH3DSP }, - { str8_lit_comp("SH4"), COFF_MachineType_SH4 }, - { str8_lit_comp("SH5"), COFF_MachineType_SH5 }, - { str8_lit_comp("THUMB"), COFF_MachineType_THUMB }, - { str8_lit_comp("WCEMIPSV2"), COFF_MachineType_WCEMIPSV2 }, + { str8_lit_comp(""), COFF_Machine_Unknown }, + { str8_lit_comp("X86"), COFF_Machine_X86 }, + { str8_lit_comp("Amd64"), COFF_Machine_X64 }, + { str8_lit_comp("X64"), COFF_Machine_X64 }, + { str8_lit_comp("Am33"), COFF_Machine_Am33 }, + { str8_lit_comp("Arm"), COFF_Machine_Arm }, + { str8_lit_comp("Arm64"), COFF_Machine_Arm64 }, + { str8_lit_comp("ArmNt"), COFF_Machine_ArmNt }, + { str8_lit_comp("Ebc"), COFF_Machine_Ebc }, + { str8_lit_comp("Ia64"), COFF_Machine_Ia64 }, + { str8_lit_comp("M32r"), COFF_Machine_M32R }, + { str8_lit_comp("Mips16"), COFF_Machine_Mips16 }, + { str8_lit_comp("MipsFpu"), COFF_Machine_MipsFpu }, + { str8_lit_comp("MipsFpu16"), COFF_Machine_MipsFpu16 }, + { str8_lit_comp("PowerPc"), COFF_Machine_PowerPc }, + { str8_lit_comp("PowerPcFp"), COFF_Machine_PowerPcFp }, + { str8_lit_comp("R4000"), COFF_Machine_R4000 }, + { str8_lit_comp("RiscV32"), COFF_Machine_RiscV32 }, + { str8_lit_comp("RiscV64"), COFF_Machine_RiscV64 }, + { str8_lit_comp("Sh3"), COFF_Machine_Sh3 }, + { str8_lit_comp("Sh3Dsp"), COFF_Machine_Sh3Dsp }, + { str8_lit_comp("Sh4"), COFF_Machine_Sh4 }, + { str8_lit_comp("Sh5"), COFF_Machine_Sh5 }, + { str8_lit_comp("Thumb"), COFF_Machine_Thumb }, + { str8_lit_comp("WceMipsV2"), COFF_Machine_WceMipsV2 }, }; read_only static struct { char * name; - COFF_ImportHeaderType type; + COFF_ImportType type; } g_coff_import_header_type_map[] = { - { "CODE", COFF_ImportHeaderType_CODE }, - { "DATA", COFF_ImportHeaderType_DATA }, - { "CONST", COFF_ImportHeaderType_CONST }, + { "Code", COFF_ImportHeader_Code }, + { "Data", COFF_ImportHeader_Data }, + { "Const", COFF_ImportHeader_Const }, }; internal String8 -coff_string_from_comdat_select_type(COFF_ComdatSelectType select) +coff_string_from_comdat_select_type(COFF_ComdatSelectType type) { - String8 result = str8(0,0); - switch (select) { - case COFF_ComdatSelectType_NULL: result = str8_lit("NULL"); break; - case COFF_ComdatSelectType_NODUPLICATES: result = str8_lit("NODUPLICATES"); break; - case COFF_ComdatSelectType_ANY: result = str8_lit("ANY"); break; - case COFF_ComdatSelectType_SAME_SIZE: result = str8_lit("SAME_SIZE"); break; - case COFF_ComdatSelectType_EXACT_MATCH: result = str8_lit("EXACT_MATCH"); break; - case COFF_ComdatSelectType_ASSOCIATIVE: result = str8_lit("ASSOCIATIVE"); break; - case COFF_ComdatSelectType_LARGEST: result = str8_lit("LARGEST"); break; + String8 result = str8_zero(); + switch (type) { + case COFF_ComdatSelect_Null: result = str8_lit("Null"); break; + case COFF_ComdatSelect_NoDuplicates: result = str8_lit("NoDuplicates"); break; + case COFF_ComdatSelect_Any: result = str8_lit("Any"); break; + case COFF_ComdatSelect_SameSize: result = str8_lit("SameSize"); break; + case COFF_ComdatSelect_ExactMatch: result = str8_lit("ExactMatch"); break; + case COFF_ComdatSelect_Associative: result = str8_lit("Associative"); break; + case COFF_ComdatSelect_Largest: result = str8_lit("Largest"); break; } return result; } @@ -85,45 +85,45 @@ coff_string_from_machine_type(COFF_MachineType machine) } internal String8 -coff_string_from_flags(Arena *arena, COFF_Flags flags) +coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags) { Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; - if (flags & COFF_Flag_RELOC_STRIPPED) { + if (flags & COFF_FileHeaderFlag_RelocStripped) { str8_list_pushf(scratch.arena, &list, "Relocs Stripped"); } - if (flags & COFF_Flag_EXECUTABLE_IMAGE) { + if (flags & COFF_FileHeaderFlag_ExecutableImage) { str8_list_pushf(scratch.arena, &list, "Executable"); } - if (flags & COFF_Flag_LINE_NUMS_STRIPPED) { + if (flags & COFF_FileHeaderFlag_LineNumbersStripped) { str8_list_pushf(scratch.arena, &list, "Line Numbers Stripped"); } - if (flags & COFF_Flag_SYM_STRIPPED) { + if (flags & COFF_FileHeaderFlag_SymbolsStripped) { str8_list_pushf(scratch.arena, &list, "Symbols Stripped"); } - if (flags & COFF_Flag_LARGE_ADDRESS_AWARE) { + if (flags & COFF_FileHeaderFlag_LargeAddressAware) { str8_list_pushf(scratch.arena, &list, "Large Address Aware"); } - if (flags & COFF_Flag_32BIT_MACHINE) { + if (flags & COFF_FileHeaderFlag_32BitMachine) { str8_list_pushf(scratch.arena, &list, "32-Bit Machine"); } - if (flags & COFF_Flag_DEBUG_STRIPPED) { + if (flags & COFF_FileHeaderFlag_DebugStripped) { str8_list_pushf(scratch.arena, &list, "Debug Stripped"); } - if (flags & COFF_Flag_REMOVABLE_RUN_FROM_SWAP) { + if (flags & COFF_FileHeaderFlag_RemovableRunFromSwap) { str8_list_pushf(scratch.arena, &list, "Removeable Run From Swap"); } - if (flags & COFF_Flag_NET_RUN_FROM_SWAP) { + if (flags & COFF_FileHeaderFlag_NetRunFromSwap) { str8_list_pushf(scratch.arena, &list, "Net Run From Swap"); } - if (flags & COFF_Flag_SYSTEM) { + if (flags & COFF_FileHeaderFlag_System) { str8_list_pushf(scratch.arena, &list, "System"); } - if (flags & COFF_Flag_DLL) { + if (flags & COFF_FileHeaderFlag_Dll) { str8_list_pushf(scratch.arena, &list, "DLL"); } - if (flags & COFF_Flag_UP_SYSTEM_ONLY) { + if (flags & COFF_FileHeaderFlag_UpSystemOnly) { str8_list_pushf(scratch.arena, &list, "Up System Only"); } @@ -139,62 +139,62 @@ coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags) Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; - if (flags & COFF_SectionFlag_TYPE_NO_PAD) { - str8_list_pushf(scratch.arena, &list, "TYPE_NO_PAD"); + if (flags & COFF_SectionFlag_TypeNoPad) { + str8_list_pushf(scratch.arena, &list, "TypeNoPad"); } - if (flags & COFF_SectionFlag_CNT_CODE) { - str8_list_pushf(scratch.arena, &list, "CNT_CODE"); + if (flags & COFF_SectionFlag_CntCode) { + str8_list_pushf(scratch.arena, &list, "CntCode"); } - if (flags & COFF_SectionFlag_CNT_INITIALIZED_DATA) { - str8_list_pushf(scratch.arena, &list, "CNT_INITIALIZED_DATA"); + if (flags & COFF_SectionFlag_CntInitializedData) { + str8_list_pushf(scratch.arena, &list, "CntInitializedData"); } - if (flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { - str8_list_pushf(scratch.arena, &list, "CNT_UNINITIALIZED_DATA"); + if (flags & COFF_SectionFlag_CntUninitializedData) { + str8_list_pushf(scratch.arena, &list, "CntUninitializedData"); } - if (flags & COFF_SectionFlag_LNK_OTHER) { - str8_list_pushf(scratch.arena, &list, "LNK_OTHER"); + if (flags & COFF_SectionFlag_LnkOther) { + str8_list_pushf(scratch.arena, &list, "LnkOther"); } - if (flags & COFF_SectionFlag_LNK_INFO) { - str8_list_pushf(scratch.arena, &list, "LNK_INFO"); + if (flags & COFF_SectionFlag_LnkInfo) { + str8_list_pushf(scratch.arena, &list, "LnkInfo"); } - if (flags & COFF_SectionFlag_LNK_COMDAT) { - str8_list_pushf(scratch.arena, &list, "LNK_COMDAT"); + if (flags & COFF_SectionFlag_LnkCOMDAT) { + str8_list_pushf(scratch.arena, &list, "LnkCOMDAT"); } - if (flags & COFF_SectionFlag_GPREL) { - str8_list_pushf(scratch.arena, &list, "GPREL"); + if (flags & COFF_SectionFlag_GpRel) { + str8_list_pushf(scratch.arena, &list, "GpRel"); } - if (flags & COFF_SectionFlag_MEM_16BIT) { - str8_list_pushf(scratch.arena, &list, "MEM_16BIT"); + if (flags & COFF_SectionFlag_Mem16Bit) { + str8_list_pushf(scratch.arena, &list, "Mem16Bit"); } - if (flags & COFF_SectionFlag_MEM_LOCKED) { - str8_list_pushf(scratch.arena, &list, "MEM_LOCKED"); + if (flags & COFF_SectionFlag_MemLocked) { + str8_list_pushf(scratch.arena, &list, "MemLocked"); } - if (flags & COFF_SectionFlag_MEM_PRELOAD) { - str8_list_pushf(scratch.arena, &list, "MEM_PRELOAD"); + if (flags & COFF_SectionFlag_MemPreload) { + str8_list_pushf(scratch.arena, &list, "MemPreload"); } - if (flags & COFF_SectionFlag_LNK_NRELOC_OVFL) { - str8_list_pushf(scratch.arena, &list, "LNK_NRELOC_OVFL"); + if (flags & COFF_SectionFlag_LnkNRelocOvfl) { + str8_list_pushf(scratch.arena, &list, "LnkNRelocOvfl"); } - if (flags & COFF_SectionFlag_MEM_DISCARDABLE) { - str8_list_pushf(scratch.arena, &list, "MEM_DISCARDABLE"); + if (flags & COFF_SectionFlag_MemDiscardable) { + str8_list_pushf(scratch.arena, &list, "MemDiscardable"); } - if (flags & COFF_SectionFlag_MEM_NOT_CACHED) { - str8_list_pushf(scratch.arena, &list, "MEM_NOT_CACHED"); + if (flags & COFF_SectionFlag_MemNotCached) { + str8_list_pushf(scratch.arena, &list, "MemNotCached"); } - if (flags & COFF_SectionFlag_MEM_NOT_PAGED) { - str8_list_pushf(scratch.arena, &list, "MEM_NOT_PAGED"); + if (flags & COFF_SectionFlag_MemNotPaged) { + str8_list_pushf(scratch.arena, &list, "MemNotPaged"); } - if (flags & COFF_SectionFlag_MEM_SHARED) { - str8_list_pushf(scratch.arena, &list, "MEM_SHARED"); + if (flags & COFF_SectionFlag_MemShared) { + str8_list_pushf(scratch.arena, &list, "MemShared"); } - if (flags & COFF_SectionFlag_MEM_EXECUTE) { - str8_list_pushf(scratch.arena, &list, "MEM_EXECUTE"); + if (flags & COFF_SectionFlag_MemExecute) { + str8_list_pushf(scratch.arena, &list, "MemExecute"); } - if (flags & COFF_SectionFlag_MEM_READ) { - str8_list_pushf(scratch.arena, &list, "MEM_READ"); + if (flags & COFF_SectionFlag_MemRead) { + str8_list_pushf(scratch.arena, &list, "MemRead"); } - if (flags & COFF_SectionFlag_MEM_WRITE) { - str8_list_pushf(scratch.arena, &list, "MEM_WRITE"); + if (flags & COFF_SectionFlag_MemWrite) { + str8_list_pushf(scratch.arena, &list, "MemWrite"); } U64 align = coff_align_size_from_section_flags(flags); @@ -215,7 +215,7 @@ coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags) } internal String8 -coff_string_from_import_header_type(COFF_ImportHeaderType type) +coff_string_from_import_header_type(COFF_ImportType type) { for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) { if (g_coff_import_header_type_map[i].type == type) { @@ -229,10 +229,10 @@ internal String8 coff_string_from_sym_dtype(COFF_SymDType x) { switch (x) { - case COFF_SymDType_NULL: return str8_lit("NULL"); - case COFF_SymDType_PTR : return str8_lit("PTR"); - case COFF_SymDType_FUNC: return str8_lit("FUNC"); - case COFF_SymDType_ARRAY: return str8_lit("ARRAY"); + case COFF_SymDType_Null: return str8_lit("Null"); + case COFF_SymDType_Ptr : return str8_lit("Ptr"); + case COFF_SymDType_Func: return str8_lit("Func"); + case COFF_SymDType_Array: return str8_lit("Array"); } return str8_zero(); } @@ -241,22 +241,22 @@ internal String8 coff_string_from_sym_type(COFF_SymType x) { switch (x) { - case COFF_SymType_NULL: return str8_lit("NULL"); - case COFF_SymType_VOID: return str8_lit("VOID"); - case COFF_SymType_CHAR: return str8_lit("CHAR"); - case COFF_SymType_SHORT: return str8_lit("SHORT"); - case COFF_SymType_INT: return str8_lit("INT"); - case COFF_SymType_LONG: return str8_lit("LONG"); - case COFF_SymType_FLOAT: return str8_lit("FLOAT"); - case COFF_SymType_DOUBLE: return str8_lit("DOUBLE"); - case COFF_SymType_STRUCT: return str8_lit("STRUCT"); - case COFF_SymType_UNION: return str8_lit("UNION"); - case COFF_SymType_ENUM: return str8_lit("ENUM"); - case COFF_SymType_MOE: return str8_lit("MOE"); - case COFF_SymType_BYTE: return str8_lit("BYTE"); - case COFF_SymType_WORD: return str8_lit("WORD"); - case COFF_SymType_UINT: return str8_lit("UINT"); - case COFF_SymType_DWORD: return str8_lit("DWORD"); + case COFF_SymType_Null: return str8_lit("Null"); + case COFF_SymType_Void: return str8_lit("Void"); + case COFF_SymType_Char: return str8_lit("Char"); + case COFF_SymType_Short: return str8_lit("Short"); + case COFF_SymType_Int: return str8_lit("Int"); + case COFF_SymType_Long: return str8_lit("Long"); + case COFF_SymType_Float: return str8_lit("Float"); + case COFF_SymType_Double: return str8_lit("Double"); + case COFF_SymType_Struct: return str8_lit("Struct"); + case COFF_SymType_Union: return str8_lit("Union"); + case COFF_SymType_Enum: return str8_lit("Enum"); + case COFF_SymType_MemberOfEnumeration: return str8_lit("MOE"); + case COFF_SymType_Byte: return str8_lit("Byte"); + case COFF_SymType_Word: return str8_lit("Word"); + case COFF_SymType_UInt: return str8_lit("UInt"); + case COFF_SymType_DWord: return str8_lit("DWord"); } return str8_zero(); } @@ -265,33 +265,33 @@ internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x) { switch (x) { - case COFF_SymStorageClass_NULL: break; - case COFF_SymStorageClass_END_OF_FUNCTION: return str8_lit("EOF"); - case COFF_SymStorageClass_AUTOMATIC: return str8_lit("AUTOMATIC"); - case COFF_SymStorageClass_EXTERNAL: return str8_lit("EXTERNAL"); - case COFF_SymStorageClass_STATIC: return str8_lit("STATIC"); - case COFF_SymStorageClass_REGISTER: return str8_lit("REGISTER"); - case COFF_SymStorageClass_EXTERNAL_DEF: return str8_lit("DEF"); - case COFF_SymStorageClass_LABEL: return str8_lit("LABEL"); - case COFF_SymStorageClass_UNDEFINED_LABEL: return str8_lit("LABEL"); - case COFF_SymStorageClass_MEMBER_OF_STRUCT: return str8_lit("STRUCT"); - case COFF_SymStorageClass_ARGUMENT: return str8_lit("ARGUMENT"); - case COFF_SymStorageClass_STRUCT_TAG: return str8_lit("TAG"); - case COFF_SymStorageClass_MEMBER_OF_UNION: return str8_lit("UNION"); - case COFF_SymStorageClass_UNION_TAG: return str8_lit("TAG"); - case COFF_SymStorageClass_TYPE_DEFINITION: return str8_lit("DEFINITION"); - case COFF_SymStorageClass_UNDEFINED_STATIC: return str8_lit("STATIC"); - case COFF_SymStorageClass_ENUM_TAG: return str8_lit("TAG"); - case COFF_SymStorageClass_MEMBER_OF_ENUM: return str8_lit("ENUM"); - case COFF_SymStorageClass_REGISTER_PARAM: return str8_lit("PARAM"); - case COFF_SymStorageClass_BIT_FIELD: return str8_lit("FIELD"); - case COFF_SymStorageClass_BLOCK: return str8_lit("BLOCK"); - case COFF_SymStorageClass_FUNCTION: return str8_lit("FUNCTION"); - case COFF_SymStorageClass_END_OF_STRUCT: return str8_lit("STRUCT"); - case COFF_SymStorageClass_FILE: return str8_lit("FILE"); - case COFF_SymStorageClass_SECTION: return str8_lit("SECTION"); - case COFF_SymStorageClass_WEAK_EXTERNAL: return str8_lit("EXTERNAL"); - case COFF_SymStorageClass_CLR_TOKEN: return str8_lit("TOKEN"); + case COFF_SymStorageClass_Null: break; + case COFF_SymStorageClass_EndOfFunction: return str8_lit("EndOfFunction"); + case COFF_SymStorageClass_Automatic: return str8_lit("Automatic"); + case COFF_SymStorageClass_External: return str8_lit("External"); + case COFF_SymStorageClass_Static: return str8_lit("Static"); + case COFF_SymStorageClass_Register: return str8_lit("Register"); + case COFF_SymStorageClass_ExternalDef: return str8_lit("Def"); + case COFF_SymStorageClass_Label: return str8_lit("Label"); + case COFF_SymStorageClass_UndefinedLabel: return str8_lit("UndefinedLabel"); + case COFF_SymStorageClass_MemberOfStruct: return str8_lit("Struct"); + case COFF_SymStorageClass_Argument: return str8_lit("Argument"); + case COFF_SymStorageClass_StructTag: return str8_lit("Tag"); + case COFF_SymStorageClass_MemberOfUnion: return str8_lit("Union"); + case COFF_SymStorageClass_UnionTag: return str8_lit("Tag"); + case COFF_SymStorageClass_TypeDefinition: return str8_lit("Definition"); + case COFF_SymStorageClass_UndefinedStatic: return str8_lit("Static"); + case COFF_SymStorageClass_EnumTag: return str8_lit("Tag"); + case COFF_SymStorageClass_MemberOfEnum: return str8_lit("Enum"); + case COFF_SymStorageClass_RegisterParam: return str8_lit("Param"); + case COFF_SymStorageClass_BitField: return str8_lit("Field"); + case COFF_SymStorageClass_Block: return str8_lit("Block"); + case COFF_SymStorageClass_Function: return str8_lit("Function"); + case COFF_SymStorageClass_EndOfStruct: return str8_lit("Struct"); + case COFF_SymStorageClass_File: return str8_lit("File"); + case COFF_SymStorageClass_Section: return str8_lit("Section"); + case COFF_SymStorageClass_WeakExternal: return str8_lit("External"); + case COFF_SymStorageClass_CLRToken: return str8_lit("Token"); } return str8_zero(); } @@ -300,130 +300,115 @@ internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x) { switch (x) { - case COFF_WeakExtType_NOLIBRARY: return str8_lit("NOLIBRARY"); - case COFF_WeakExtType_SEARCH_LIBRARY: return str8_lit("SEARCH_LIBRARY"); - case COFF_WeakExtType_SEARCH_ALIAS: return str8_lit("SEARCH_ALIAS"); + case COFF_WeakExt_NoLibrary: return str8_lit("NoLibrary"); + case COFF_WeakExt_SearchLibrary: return str8_lit("SearchLibrary"); + case COFF_WeakExt_SearchAlias: return str8_lit("SearchAlias"); } return str8_zero(); } internal String8 -coff_string_from_selection(COFF_ComdatSelectType x) +coff_string_from_reloc_x86(COFF_Reloc_X86 x) { switch (x) { - case COFF_ComdatSelectType_NULL: break; - case COFF_ComdatSelectType_NODUPLICATES: return str8_lit("NODUPLICATES"); - case COFF_ComdatSelectType_ANY: return str8_lit("ANY"); - case COFF_ComdatSelectType_SAME_SIZE: return str8_lit("SIZE"); - case COFF_ComdatSelectType_EXACT_MATCH: return str8_lit("MATCH"); - case COFF_ComdatSelectType_ASSOCIATIVE: return str8_lit("ASSOCIATIVE"); - case COFF_ComdatSelectType_LARGEST: return str8_lit("LARGEST"); + case COFF_Reloc_X86_Abs: return str8_lit("Abs"); + case COFF_Reloc_X86_Dir16: return str8_lit("Dir16"); + case COFF_Reloc_X86_Rel16: return str8_lit("Rel16"); + case COFF_Reloc_X86_Unknown0: return str8_lit("Unknown0"); + case COFF_Reloc_X86_Unknown2: return str8_lit("Unknown2"); + case COFF_Reloc_X86_Unknown3: return str8_lit("Unknown3"); + case COFF_Reloc_X86_Dir32: return str8_lit("Dir32"); + case COFF_Reloc_X86_Dir32Nb: return str8_lit("Dir32Nb"); + case COFF_Reloc_X86_Seg12: return str8_lit("Seg12"); + case COFF_Reloc_X86_Section: return str8_lit("Section"); + case COFF_Reloc_X86_SecRel: return str8_lit("SecRel"); + case COFF_Reloc_X86_Token: return str8_lit("Token"); + case COFF_Reloc_X86_SecRel7: return str8_lit("SecRel7"); + case COFF_Reloc_X86_Unknown4: return str8_lit("Unknown4"); + case COFF_Reloc_X86_Unknown5: return str8_lit("Unknown5"); + case COFF_Reloc_X86_Unknown6: return str8_lit("Unknown6"); + case COFF_Reloc_X86_Unknown7: return str8_lit("Unknown7"); + case COFF_Reloc_X86_Unknown8: return str8_lit("Unknown8"); + case COFF_Reloc_X86_Unknown9: return str8_lit("Unknown9"); + case COFF_Reloc_X86_Rel32: return str8_lit("Rel32"); } return str8_zero(); } internal String8 -coff_string_from_reloc_x86(COFF_RelocTypeX86 x) +coff_string_from_reloc_x64(COFF_Reloc_X64 x) { switch (x) { - case COFF_RelocTypeX86_ABS: return str8_lit("ABS"); - case COFF_RelocTypeX86_DIR16: return str8_lit("DIR16"); - case COFF_RelocTypeX86_REL16: return str8_lit("REL16"); - case COFF_RelocTypeX86_UNKNOWN0: return str8_lit("UNKNOWN0"); - case COFF_RelocTypeX86_UNKNOWN2: return str8_lit("UNKNOWN2"); - case COFF_RelocTypeX86_UNKNOWN3: return str8_lit("UNKNOWN3"); - case COFF_RelocTypeX86_DIR32: return str8_lit("DIR32"); - case COFF_RelocTypeX86_DIR32NB: return str8_lit("DIR32NB"); - case COFF_RelocTypeX86_SEG12: return str8_lit("SEG12"); - case COFF_RelocTypeX86_SECTION: return str8_lit("SECTION"); - case COFF_RelocTypeX86_SECREL: return str8_lit("SECREL"); - case COFF_RelocTypeX86_TOKEN: return str8_lit("TOKEN"); - case COFF_RelocTypeX86_SECREL7: return str8_lit("SECREL7"); - case COFF_RelocTypeX86_UNKNOWN4: return str8_lit("UNKNOWN4"); - case COFF_RelocTypeX86_UNKNOWN5: return str8_lit("UNKNOWN5"); - case COFF_RelocTypeX86_UNKNOWN6: return str8_lit("UNKNOWN6"); - case COFF_RelocTypeX86_UNKNOWN7: return str8_lit("UNKNOWN7"); - case COFF_RelocTypeX86_UNKNOWN8: return str8_lit("UNKNOWN8"); - case COFF_RelocTypeX86_UNKNOWN9: return str8_lit("UNKNOWN9"); - case COFF_RelocTypeX86_REL32: return str8_lit("REL32"); + case COFF_Reloc_X64_Abs: return str8_lit("Abs"); + case COFF_Reloc_X64_Addr64: return str8_lit("Addr64"); + case COFF_Reloc_X64_Addr32: return str8_lit("Addr32"); + case COFF_Reloc_X64_Addr32Nb: return str8_lit("Addr32Nb"); + case COFF_Reloc_X64_Rel32: return str8_lit("Rel32"); + case COFF_Reloc_X64_Rel32_1: return str8_lit("Rel32_1"); + case COFF_Reloc_X64_Rel32_2: return str8_lit("Rel32_2"); + case COFF_Reloc_X64_Rel32_3: return str8_lit("Rel32_3"); + case COFF_Reloc_X64_Rel32_4: return str8_lit("Rel32_4"); + case COFF_Reloc_X64_Rel32_5: return str8_lit("Rel32_5"); + case COFF_Reloc_X64_Section: return str8_lit("Section"); + case COFF_Reloc_X64_SecRel: return str8_lit("SecRel"); + case COFF_Reloc_X64_SecRel7: return str8_lit("SecRel7"); + case COFF_Reloc_X64_Token: return str8_lit("Token"); + case COFF_Reloc_X64_SRel32: return str8_lit("SRel32"); + case COFF_Reloc_X64_Pair: return str8_lit("Pair"); + case COFF_Reloc_X64_SSpan32: return str8_lit("SSpan32"); } return str8_zero(); } internal String8 -coff_string_from_reloc_x64(COFF_RelocTypeX64 x) +coff_string_from_reloc_arm(COFF_Reloc_Arm x) { switch (x) { - case COFF_RelocTypeX64_ABS: return str8_lit("ABS"); - case COFF_RelocTypeX64_ADDR64: return str8_lit("ADDR64"); - case COFF_RelocTypeX64_ADDR32: return str8_lit("ADDR32"); - case COFF_RelocTypeX64_ADDR32NB: return str8_lit("ADDR32NB"); - case COFF_RelocTypeX64_REL32: return str8_lit("REL32"); - case COFF_RelocTypeX64_REL32_1: return str8_lit("REL32_1"); - case COFF_RelocTypeX64_REL32_2: return str8_lit("REL32_2"); - case COFF_RelocTypeX64_REL32_3: return str8_lit("REL32_3"); - case COFF_RelocTypeX64_REL32_4: return str8_lit("REL32_4"); - case COFF_RelocTypeX64_REL32_5: return str8_lit("REL32_5"); - case COFF_RelocTypeX64_SECTION: return str8_lit("SECTION"); - case COFF_RelocTypeX64_SECREL: return str8_lit("SECREL"); - case COFF_RelocTypeX64_SECREL7: return str8_lit("SECREL7"); - case COFF_RelocTypeX64_TOKEN: return str8_lit("TOKEN"); - case COFF_RelocTypeX64_SREL32: return str8_lit("SREL32"); - case COFF_RelocTypeX64_PAIR: return str8_lit("PAIR"); - case COFF_RelocTypeX64_SSPAN32: return str8_lit("SSPAN32"); + case COFF_Reloc_Arm_Abs: return str8_lit("Abs"); + case COFF_Reloc_Arm_Addr32: return str8_lit("Addr32"); + case COFF_Reloc_Arm_Addr32Nb: return str8_lit("Addr32Nb"); + case COFF_Reloc_Arm_Branch24: return str8_lit("Branch24"); + case COFF_Reloc_Arm_Branch11: return str8_lit("Branch11"); + case COFF_Reloc_Arm_Unknown1: return str8_lit("Unknown1"); + case COFF_Reloc_Arm_Unknown2: return str8_lit("Unknown2"); + case COFF_Reloc_Arm_Unknown3: return str8_lit("Unknown3"); + case COFF_Reloc_Arm_Unknown4: return str8_lit("Unknown4"); + case COFF_Reloc_Arm_Unknown5: return str8_lit("Unknown5"); + case COFF_Reloc_Arm_Rel32: return str8_lit("Rel32"); + case COFF_Reloc_Arm_Section: return str8_lit("Section"); + case COFF_Reloc_Arm_SecRel: return str8_lit("SecRel"); + case COFF_Reloc_Arm_Mov32: return str8_lit("Mov32"); + case COFF_Reloc_Arm_ThumbMov32: return str8_lit("ThumbMov32"); + case COFF_Reloc_Arm_ThumbBranch20: return str8_lit("ThumbBranch20"); + case COFF_Reloc_Arm_Unused: return str8_lit("Unused"); + case COFF_Reloc_Arm_ThumbBranch24: return str8_lit("ThumbBranch24"); + case COFF_Reloc_Arm_ThumbBlx23: return str8_lit("ThumbBlx23"); + case COFF_Reloc_Arm_Pair: return str8_lit("Pair"); } return str8_zero(); } internal String8 -coff_string_from_reloc_arm(COFF_RelocTypeARM x) +coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x) { switch (x) { - case COFF_RelocTypeARM_ABS: return str8_lit("ABS"); - case COFF_RelocTypeARM_ADDR32: return str8_lit("ADDR32"); - case COFF_RelocTypeARM_ADDR32NB: return str8_lit("ADDR32NB"); - case COFF_RelocTypeARM_BRANCH24: return str8_lit("BRANCH24"); - case COFF_RelocTypeARM_BRANCH11: return str8_lit("BRANCH11"); - case COFF_RelocTypeARM_UNKNOWN1: return str8_lit("UNKNOWN1"); - case COFF_RelocTypeARM_UNKNOWN2: return str8_lit("UNKNOWN2"); - case COFF_RelocTypeARM_UNKNOWN3: return str8_lit("UNKNOWN3"); - case COFF_RelocTypeARM_UNKNOWN4: return str8_lit("UNKNOWN4"); - case COFF_RelocTypeARM_UNKNOWN5: return str8_lit("UNKNOWN5"); - case COFF_RelocTypeARM_REL32: return str8_lit("REL32"); - case COFF_RelocTypeARM_SECTION: return str8_lit("SECTION"); - case COFF_RelocTypeARM_SECREL: return str8_lit("SECREL"); - case COFF_RelocTypeARM_MOV32: return str8_lit("MOV32"); - case COFF_RelocTypeARM_THUMB_MOV32: return str8_lit("THUMB_MOV32"); - case COFF_RelocTypeARM_THUMB_BRANCH20: return str8_lit("THUMB_BRANCH20"); - case COFF_RelocTypeARM_UNUSED: return str8_lit("UNUSED"); - case COFF_RelocTypeARM_THUMB_BRANCH24: return str8_lit("THUMB_BRANCH24"); - case COFF_RelocTypeARM_THUMB_BLX23: return str8_lit("THUMB_BLX23"); - case COFF_RelocTypeARM_PAIR: return str8_lit("PAIR"); - } - return str8_zero(); -} - -internal String8 -coff_string_from_reloc_arm64(COFF_RelocTypeARM64 x) -{ - switch (x) { - case COFF_RelocTypeARM64_ABS: return str8_lit("ABS"); - case COFF_RelocTypeARM64_ADDR32: return str8_lit("ADDR32"); - case COFF_RelocTypeARM64_ADDR32NB: return str8_lit("ADDR32NB"); - case COFF_RelocTypeARM64_BRANCH26: return str8_lit("BRANCH26"); - case COFF_RelocTypeARM64_PAGEBASE_REL21: return str8_lit("PAGEBASE_REL21"); - case COFF_RelocTypeARM64_REL21: return str8_lit("REL21"); - case COFF_RelocTypeARM64_PAGEOFFSET_12A: return str8_lit("PAGEOFFSET_12A"); - case COFF_RelocTypeARM64_SECREL: return str8_lit("SECREL"); - case COFF_RelocTypeARM64_SECREL_LOW12A: return str8_lit("SECREL_LOW12A"); - case COFF_RelocTypeARM64_SECREL_HIGH12A: return str8_lit("SECREL_HIGH12A"); - case COFF_RelocTypeARM64_SECREL_LOW12L: return str8_lit("SECREL_LOW12L"); - case COFF_RelocTypeARM64_TOKEN: return str8_lit("TOKEN"); - case COFF_RelocTypeARM64_SECTION: return str8_lit("SECTION"); - case COFF_RelocTypeARM64_ADDR64: return str8_lit("ADDR64"); - case COFF_RelocTypeARM64_BRANCH19: return str8_lit("BRANCH19"); - case COFF_RelocTypeARM64_BRANCH14: return str8_lit("BRANCH14"); - case COFF_RelocTypeARM64_REL32: return str8_lit("REL32"); + case COFF_Reloc_Arm64_Abs: return str8_lit("Abs"); + case COFF_Reloc_Arm64_Addr32: return str8_lit("Addr32"); + case COFF_Reloc_Arm64_Addr32Nb: return str8_lit("Addr32Nb"); + case COFF_Reloc_Arm64_Branch26: return str8_lit("Branch26"); + case COFF_Reloc_Arm64_PageBaseRel21: return str8_lit("PageBaseRel21"); + case COFF_Reloc_Arm64_Rel21: return str8_lit("Rel21"); + case COFF_Reloc_Arm64_PageOffset12a: return str8_lit("PageOffset12a"); + case COFF_Reloc_Arm64_SecRel: return str8_lit("SecRel"); + case COFF_Reloc_Arm64_SecRelLow12a: return str8_lit("SecRelLow12a"); + case COFF_Reloc_Arm64_SecRelHigh12a: return str8_lit("SecRelHigh12a"); + case COFF_Reloc_Arm64_SecRelLow12l: return str8_lit("SecRelLow12l"); + case COFF_Reloc_Arm64_Token: return str8_lit("Token"); + case COFF_Reloc_Arm64_Section: return str8_lit("Section"); + case COFF_Reloc_Arm64_Addr64: return str8_lit("Addr64"); + case COFF_Reloc_Arm64_Branch19: return str8_lit("Branch19"); + case COFF_Reloc_Arm64_Branch14: return str8_lit("Branch14"); + case COFF_Reloc_Arm64_Rel32: return str8_lit("Rel32"); } return str8_zero(); } @@ -432,10 +417,10 @@ internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x) { switch (machine) { - case COFF_MachineType_X86: return coff_string_from_reloc_x86(x); - case COFF_MachineType_X64: return coff_string_from_reloc_x64(x); - case COFF_MachineType_ARM: return coff_string_from_reloc_arm(x); - case COFF_MachineType_ARM64: return coff_string_from_reloc_arm64(x); + case COFF_Machine_X86: return coff_string_from_reloc_x86(x); + case COFF_Machine_X64: return coff_string_from_reloc_x64(x); + case COFF_Machine_Arm: return coff_string_from_reloc_arm(x); + case COFF_Machine_Arm64: return coff_string_from_reloc_arm64(x); } return str8_zero(); } @@ -448,10 +433,10 @@ coff_machine_from_string(String8 string) return g_coff_machine_map[i].machine; } } - return COFF_MachineType_UNKNOWN; + return COFF_Machine_Unknown; } -internal COFF_ImportHeaderType +internal COFF_ImportType coff_import_header_type_from_string(String8 name) { for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) { @@ -459,7 +444,7 @@ coff_import_header_type_from_string(String8 name) return g_coff_import_header_type_map[i].type; } } - return COFF_ImportHeaderType_COUNT; + return COFF_ImportType_Invalid; } diff --git a/src/coff/coff_enum.h b/src/coff/coff_enum.h index 7eb174e7..a294b5a2 100644 --- a/src/coff/coff_enum.h +++ b/src/coff/coff_enum.h @@ -5,23 +5,22 @@ #define COFF_ENUM_H internal String8 coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp); -internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType select); +internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType type); internal String8 coff_string_from_machine_type(COFF_MachineType machine); -internal String8 coff_string_from_flags(Arena *arena, COFF_Flags flags); +internal String8 coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags); internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags); -internal String8 coff_string_from_import_header_type(COFF_ImportHeaderType type); +internal String8 coff_string_from_import_header_type(COFF_ImportType type); internal String8 coff_string_from_sym_dtype(COFF_SymDType x); internal String8 coff_string_from_sym_type(COFF_SymType x); internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x); internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x); -internal String8 coff_string_from_selection(COFF_ComdatSelectType x); -internal String8 coff_string_from_reloc_x86(COFF_RelocTypeX86 x); -internal String8 coff_string_from_reloc_x64(COFF_RelocTypeX64 x); -internal String8 coff_string_from_reloc_arm(COFF_RelocTypeARM x); -internal String8 coff_string_from_reloc_arm64(COFF_RelocTypeARM64 x); +internal String8 coff_string_from_reloc_x86(COFF_Reloc_X86 x); +internal String8 coff_string_from_reloc_x64(COFF_Reloc_X64 x); +internal String8 coff_string_from_reloc_arm(COFF_Reloc_Arm x); +internal String8 coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x); internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x); -internal COFF_MachineType coff_machine_from_string(String8 string); -internal COFF_ImportHeaderType coff_import_header_type_from_string(String8 name); +internal COFF_MachineType coff_machine_from_string(String8 string); +internal COFF_ImportType coff_import_header_type_from_string(String8 name); #endif // COFF_ENUM_H diff --git a/src/coff/coff_parse.c b/src/coff/coff_parse.c new file mode 100644 index 00000000..aa33fb07 --- /dev/null +++ b/src/coff/coff_parse.c @@ -0,0 +1,904 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +internal B32 +coff_is_big_obj(String8 raw_coff) +{ + B32 is_big_obj = 0; + if (raw_coff.size >= sizeof(COFF_BigObjHeader)) { + COFF_BigObjHeader *file_header32 = (COFF_BigObjHeader*)(raw_coff.str); + is_big_obj = file_header32->sig1 == COFF_Machine_Unknown && + file_header32->sig2 == max_U16 && + file_header32->version >= 2 && + MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0; + } + return is_big_obj; +} + +internal B32 +coff_is_obj(String8 raw_coff) +{ + B32 is_obj = 0; + + if (raw_coff.size >= sizeof(COFF_FileHeader)) { + COFF_FileHeader *header = (COFF_FileHeader*)(raw_coff.str); + + // validate machine + B32 is_machine_type_valid = 0; + switch (header->machine) { + case COFF_Machine_Unknown: + case COFF_Machine_X86: case COFF_Machine_X64: + case COFF_Machine_Am33: case COFF_Machine_Arm: + case COFF_Machine_Arm64: case COFF_Machine_ArmNt: + case COFF_Machine_Ebc: case COFF_Machine_Ia64: + case COFF_Machine_M32R: case COFF_Machine_Mips16: + case COFF_Machine_MipsFpu:case COFF_Machine_MipsFpu16: + case COFF_Machine_PowerPc:case COFF_Machine_PowerPcFp: + case COFF_Machine_R4000: case COFF_Machine_RiscV32: + case COFF_Machine_RiscV64:case COFF_Machine_RiscV128: + case COFF_Machine_Sh3: case COFF_Machine_Sh3Dsp: + case COFF_Machine_Sh4: case COFF_Machine_Sh5: + case COFF_Machine_Thumb: case COFF_Machine_WceMipsV2: + { + is_machine_type_valid = 1; + }break; + } + + if (is_machine_type_valid) { + // validate section count + U64 section_count = header->section_count; + U64 section_hdr_opl_off = sizeof(*header) + section_count*sizeof(COFF_SectionHeader); + if (raw_coff.size >= section_hdr_opl_off) { + + COFF_SectionHeader *section_hdrs = (COFF_SectionHeader*)(raw_coff.str + sizeof(*header)); + COFF_SectionHeader *section_hdr_opl = section_hdrs + section_count; + + // validate section ranges + B32 is_sect_range_valid = 1; + for (COFF_SectionHeader *sec_hdr = section_hdrs; + sec_hdr < section_hdr_opl; + sec_hdr += 1) { + if (!(sec_hdr->flags & COFF_SectionFlag_CntUninitializedData)) { + U64 min = sec_hdr->foff; + U64 max = min + sec_hdr->fsize; + if (sec_hdr->fsize > 0 && !(section_hdr_opl_off <= min && min <= max && max <= raw_coff.size)) { + is_sect_range_valid = 0; + break; + } + } + } + + if (is_sect_range_valid) { + // validate symbol table + U64 symbol_table_off = header->symbol_table_foff; + U64 symbol_table_size = sizeof(COFF_Symbol16)*header->symbol_count; + U64 symbol_table_opl_off = symbol_table_off + symbol_table_size; + + // don't validate symbol table when there is none + if (symbol_table_off == 0 && symbol_table_size == 0) { + symbol_table_off = section_hdr_opl_off; + symbol_table_opl_off = section_hdr_opl_off; + } + + is_obj = (section_hdr_opl_off <= symbol_table_off && + symbol_table_off <= symbol_table_opl_off && + symbol_table_opl_off <= raw_coff.size); + } + } + } + } + + return is_obj; +} + +internal COFF_FileHeaderInfo +coff_file_header_info_from_data(String8 raw_coff) +{ + COFF_FileHeaderInfo info = {0}; + if (coff_is_big_obj(raw_coff)) { + COFF_BigObjHeader *header32 = (COFF_BigObjHeader*)raw_coff.str; + info.is_big_obj = 1; + info.machine = header32->machine; + info.header_size = sizeof(COFF_BigObjHeader); + info.section_array_off = sizeof(COFF_BigObjHeader); + info.section_count_no_null = header32->section_count; + info.string_table_off = header32->symbol_table_foff + sizeof(COFF_Symbol32) * header32->symbol_count; + info.symbol_size = sizeof(COFF_Symbol32); + info.symbol_off = header32->symbol_table_foff; + info.symbol_count = header32->symbol_count; + } else if (coff_is_obj(raw_coff)) { + COFF_FileHeader *header16 = (COFF_FileHeader*)raw_coff.str; + info.is_big_obj = 0; + info.machine = header16->machine; + info.header_size = sizeof(COFF_FileHeader); + info.section_array_off = sizeof(COFF_FileHeader); + info.section_count_no_null = header16->section_count; + info.string_table_off = header16->symbol_table_foff + sizeof(COFF_Symbol16) * header16->symbol_count; + info.symbol_size = sizeof(COFF_Symbol16); + info.symbol_off = header16->symbol_table_foff; + info.symbol_count = header16->symbol_count; + } + return info; +} + +internal COFF_ParsedSymbol +coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32) +{ + COFF_ParsedSymbol result = {0}; + result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym32->name); + result.value = sym32->value; + result.section_number = sym32->section_number; + result.type = sym32->type; + result.storage_class = sym32->storage_class; + result.aux_symbol_count = sym32->aux_symbol_count; + return result; +} + +internal COFF_ParsedSymbol +coff_parse_symbol16(String8 raw_coff, U64 string_table_off, COFF_Symbol16 *sym16) +{ + COFF_ParsedSymbol result = {0}; + result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym16->name); + result.value = sym16->value; + if (sym16->section_number == COFF_Symbol_DebugSection16) { + result.section_number = COFF_Symbol_DebugSection32; + } else if (sym16->section_number == COFF_Symbol_AbsSection16) { + result.section_number = COFF_Symbol_AbsSection32; + } else { + result.section_number = (U32)sym16->section_number; + } + result.type = sym16->type; + result.storage_class = sym16->storage_class; + result.aux_symbol_count = sym16->aux_symbol_count; + return result; +} + +internal COFF_Symbol32Array +coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count) +{ + COFF_Symbol32Array result = {0}; + result.count = symbol_count; + result.v = push_array_no_zero_aligned(arena, COFF_Symbol32, result.count, 8); + + Rng1U64 sym16_arr_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count); + String8 raw_sym16_arr = str8_substr(raw_coff, sym16_arr_range); + COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)raw_sym16_arr.str; + + for (U64 isymbol = 0, count = raw_sym16_arr.size / sizeof(COFF_Symbol16); isymbol < count; isymbol += 1) { + COFF_Symbol16 *sym16 = &sym16_arr[isymbol]; + COFF_Symbol32 *sym32 = &result.v[isymbol]; + + sym32->name = sym16->name; + sym32->value = sym16->value; + if (sym16->section_number == COFF_Symbol_DebugSection16) { + sym32->section_number = COFF_Symbol_DebugSection32; + } else if (sym16->section_number == COFF_Symbol_AbsSection16) { + sym32->section_number = COFF_Symbol_AbsSection32; + } else { + sym32->section_number = (U32)sym16->section_number; + } + sym32->type.v = sym16->type.v; + sym32->storage_class = sym16->storage_class; + sym32->aux_symbol_count = sym16->aux_symbol_count; + + // copy aux symbols + for (U64 iaux = isymbol+1, iaux_hi = Min(count, iaux+sym16->aux_symbol_count); iaux < iaux_hi; iaux += 1) { + COFF_Symbol16 *aux16 = sym16_arr + iaux; + COFF_Symbol32 *aux32 = result.v + iaux; + + // 32bit COFF uses 16bit aux symbols + MemoryCopy(aux32, aux16, sizeof(COFF_Symbol16)); + MemoryZero((U8 *)aux32 + sizeof(COFF_Symbol16), sizeof(COFF_Symbol32)-sizeof(COFF_Symbol16)); + } + + // take into account aux symbols + isymbol += sym32->aux_symbol_count; + } + + return result; +} + +internal COFF_Symbol32Array +coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count) +{ + COFF_Symbol32Array result; + result.count = symbol_count; + result.v = (COFF_Symbol32 *)(data.str + symbol_array_off); + return result; +} + +internal COFF_Symbol32Array +coff_symbol_array_from_data(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count, U64 symbol_size) +{ + COFF_Symbol32Array result = {0}; + switch (symbol_size) { + case sizeof(COFF_Symbol16): result = coff_symbol_array_from_data_16(arena, data, symbol_array_off, symbol_count); break; + case sizeof(COFF_Symbol32): result = coff_symbol_array_from_data_32(arena, data, symbol_array_off, symbol_count); break; + } + return result; +} + +internal COFF_Symbol16Node * +coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol) +{ + COFF_Symbol16Node *node = push_array(arena, COFF_Symbol16Node, 1); + node->next = 0; + node->data = symbol; + SLLQueuePush(list->first, list->last, node); + list->count += 1; + return node; +} + +internal COFF_SymbolValueInterpType +coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class) +{ + if (storage_class == COFF_SymStorageClass_Section && section_number == COFF_Symbol_UndefinedSection) { + return COFF_SymbolValueInterp_Undefined; + } + if (storage_class == COFF_SymStorageClass_External && value == 0 && section_number == COFF_Symbol_UndefinedSection) { + return COFF_SymbolValueInterp_Undefined; + } + if (storage_class == COFF_SymStorageClass_External && value != 0 && section_number == COFF_Symbol_UndefinedSection) { + return COFF_SymbolValueInterp_Common; + } + if (section_number == COFF_Symbol_AbsSection32) { + return COFF_SymbolValueInterp_Abs; + } + if (section_number == COFF_Symbol_DebugSection32) { + return COFF_SymbolValueInterp_Debug; + } + if (storage_class == COFF_SymStorageClass_WeakExternal) { + return COFF_SymbolValueInterp_Weak; + } + return COFF_SymbolValueInterp_Regular; +} + +internal COFF_RelocNode * +coff_reloc_list_push(Arena *arena, COFF_RelocList *list, COFF_Reloc reloc) +{ + COFF_RelocNode *node = push_array(arena, COFF_RelocNode, 1); + node->data = reloc; + SLLQueuePush(list->first, list->last, node); + ++list->count; + return node; +} + +internal COFF_RelocInfo +coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header) +{ + COFF_RelocInfo result = {0}; + if (header->flags & COFF_SectionFlag_LnkNRelocOvfl && header->reloc_count == max_U16) { + COFF_Reloc counter; + U64 read_size = str8_deserial_read_struct(data, header->relocs_foff, &counter); + if (read_size == sizeof(counter) && counter.apply_off > 0) { + result.array_off = header->relocs_foff + sizeof(COFF_Reloc); + result.count = counter.apply_off - 1; // exclude counter entry + } + } else { + result.array_off = header->relocs_foff; + result.count = header->reloc_count; + } + return result; +} + +internal String8 +coff_resource_string_from_str16(Arena *arena, String16 string) +{ + AssertAlways(string.size <= max_U16); + U16 size16 = (U16)string.size; + + U16 *buffer = push_array_no_zero(arena, U16, size16 + 1); + MemoryCopy(buffer + 0, &size16, sizeof(size16)); + MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0])); + + return str8_array(buffer, size16 + 1); +} + +internal String8 +coff_resource_string_from_str8(Arena *arena, String8 string) +{ + Temp scratch = scratch_begin(&arena, 1); + String16 string16 = str16_from_8(scratch.arena, string); + String8 result = coff_resource_string_from_str16(arena, string16); + scratch_end(scratch); + return result; +} + +internal String8 +coff_resource_number_from_u16(Arena *arena, U16 number) +{ + U16 *buffer = push_array_no_zero(arena, U16, 2); + buffer[0] = max_U16; + buffer[1] = number; + return str8_array(buffer, 2); +} + +internal COFF_ResourceID +coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID16 *id_16) +{ + COFF_ResourceID id = {0}; + id.type = id_16->type; + switch (id_16->type) { + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_Number: { + id.u.number = id_16->u.number; + } break; + case COFF_ResourceIDType_String: { + id.u.string = str8_from_16(arena, id_16->u.string); + } break; + default: InvalidPath; + } + return id; +} + +internal U64 +coff_read_resource_id_utf16(String8 raw_res, U64 off, COFF_ResourceID16 *id_out) +{ + U64 cursor = off; + + U16 flag = 0; + str8_deserial_read_struct(raw_res, cursor, &flag); + + if (flag == max_U16) { + id_out->type = COFF_ResourceIDType_Number; + cursor += sizeof(flag); + cursor += str8_deserial_read_struct(raw_res, cursor, &id_out->u.number); + } else { + id_out->type = COFF_ResourceIDType_String; + cursor += str8_deserial_read_windows_utf16_string16(raw_res, cursor, &id_out->u.string); + } + + U64 read_size = cursor - off; + read_size = AlignPow2(read_size, COFF_ResourceAlign); + return read_size; +} + +internal U64 +coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *res_out) +{ + String8 raw_header = str8_skip(raw_res, off); + U64 header_cursor = 0; + + // prefix + COFF_ResourceHeaderPrefix prefix = {0}; + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix); + + Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix)); + raw_header = str8_prefix(raw_header, prefix.header_size); + + // header + COFF_ResourceID16 type_16 = {0}; + COFF_ResourceID16 name_16 = {0}; + header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &type_16); + header_cursor += coff_read_resource_id_utf16(raw_header, header_cursor, &name_16); + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->data_version); + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->memory_flags); + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->language_id); + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version); + header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics); + Assert(prefix.header_size == header_cursor); + + // convert utf-16 resource ids to utf-8 + res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16); + res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16); + + // read data + U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data); + Assert(prefix.data_size == data_read_size); + + // compute read size + U64 read_size = Max(prefix.header_size, sizeof(prefix)) + AlignPow2(prefix.data_size, COFF_ResourceAlign); + return read_size; +} + +internal COFF_ParsedResourceList +coff_resource_list_from_data(Arena *arena, String8 data) +{ + COFF_ParsedResourceList list = {0}; + U64 cursor; + for (cursor = 0 ; cursor < data.size; ) { + COFF_ParsedResourceNode *node = push_array(arena, COFF_ParsedResourceNode, 1); + cursor += coff_read_resource(arena, data, cursor, &node->data); + SLLQueuePush(list.first, list.last, node); + ++list.count; + } + Assert(cursor == data.size); + return list; +} + +internal String8 +coff_write_resource_id(Arena *arena, COFF_ResourceID id) +{ + String8 result = str8_zero(); + switch (id.type) { + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_Number: { + result = coff_resource_number_from_u16(arena, id.u.number); + } break; + case COFF_ResourceIDType_String: { + result = coff_resource_string_from_str8(arena, id.u.string); + } break; + default: InvalidPath; + } + return result; +} + +internal String8 +coff_write_resource(Arena *arena, + COFF_ResourceID type, + COFF_ResourceID name, + U32 data_version, + COFF_ResourceMemoryFlags memory_flags, + U16 language_id, + U32 version, + U32 characteristics, + String8 data) +{ + Temp scratch = scratch_begin(&arena, 1); + + String8List list = {0}; + + COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1); + String8 packed_type = coff_write_resource_id(scratch.arena, type); + String8 packed_name = coff_write_resource_id(scratch.arena, name); + + // prefix + header + str8_list_push(scratch.arena, &list, str8_struct(prefix)); + str8_list_push(scratch.arena, &list, packed_type); + str8_list_push(scratch.arena, &list, packed_name); + str8_list_push(scratch.arena, &list, str8_struct(&data_version)); + str8_list_push(scratch.arena, &list, str8_struct(&memory_flags)); + str8_list_push(scratch.arena, &list, str8_struct(&language_id)); + str8_list_push(scratch.arena, &list, str8_struct(&version)); + str8_list_push(scratch.arena, &list, str8_struct(&characteristics)); + + prefix->data_size = safe_cast_u32(data.size); + prefix->header_size = safe_cast_u32(list.total_size); + + // data + str8_list_push(scratch.arena, &list, data); + + // magic + str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic)); + + // align + U64 align_size = AlignPow2(list.total_size, COFF_ResourceAlign) - list.total_size; + U8 *align = push_array(scratch.arena, U8, align_size); + str8_list_push(scratch.arena, &list, str8(align, align_size)); + + // join + String8 res = str8_list_join(arena, &list, 0); + + scratch_end(scratch); + return res; +} + +internal int +coff_resource_id_compar(void *raw_a, void *raw_b) +{ + int cmp; + COFF_ResourceID *a = raw_b; + COFF_ResourceID *b = raw_b; + if (a->type == b->type) { + switch (a->type) { + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_Number: cmp = u16_compar(&a->u.number, &b->u.number); break; + case COFF_ResourceIDType_String: cmp = str8_compar_case_sensitive(&a->u.string, &b->u.string); break; + default: InvalidPath; break; + } + } else { + cmp = u32_compar(&a->type, &b->type); + } + return cmp; +} + +internal B32 +coff_is_import(String8 raw_archive_member) +{ + B32 is_import = 0; + if (raw_archive_member.size >= sizeof(U16)*2) { + U16 *sig1 = (U16*)raw_archive_member.str; + U16 *sig2 = sig1 + 1; + is_import = *sig1 == COFF_Machine_Unknown && *sig2 == 0xffff; + } + return is_import; +} + +internal COFF_DataType +coff_data_type_from_data(String8 raw_archive_member) +{ + B32 is_big_obj = coff_is_big_obj(raw_archive_member); + if (is_big_obj) { + return COFF_DataType_BigObj; + } + B32 is_import = coff_is_import(raw_archive_member); + if (is_import) { + return COFF_DataType_Import; + } + return COFF_DataType_Obj; +} + +internal B32 +coff_is_regular_archive(String8 raw_archive) +{ + B32 is_archive = 0; + U8 sig[sizeof(g_coff_archive_sig)]; + if (str8_deserial_read_struct(raw_archive, 0, &sig) == sizeof(sig)) { + is_archive = MemoryCompare(&sig[0], &g_coff_archive_sig[0], sizeof(g_coff_archive_sig)) == 0; + } + return is_archive; +} + +internal B32 +coff_is_thin_archive(String8 raw_archive) +{ + B32 is_archive = 0; + U8 sig[sizeof(g_coff_thin_archive_sig)]; + if (str8_deserial_read_struct(raw_archive, 0, &sig) == sizeof(sig)) { + is_archive = MemoryCompare(&sig[0], &g_coff_thin_archive_sig[0], sizeof(g_coff_thin_archive_sig)) == 0; + } + return is_archive; +} + +internal COFF_ArchiveType +coff_archive_type_from_data(String8 raw_archive) +{ + if (coff_is_regular_archive(raw_archive)) { + return COFF_Archive_Regular; + } else if (coff_is_thin_archive(raw_archive)) { + return COFF_Archive_Thin; + } + return COFF_Archive_Null; +} + +internal U64 +coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArchiveMemberHeader *header_out) +{ + COFF_ArchiveMemberHeader *header = str8_deserial_get_raw_ptr(raw_archive, offset, sizeof(*header)); + if (header) { + String8 name = str8_skip_chop_whitespace(str8_cstring_capped(header->name, header->name + sizeof(header->name) )); + String8 date = str8_skip_chop_whitespace(str8_cstring_capped(header->date, header->date + sizeof(header->date) )); + String8 user_id = str8_skip_chop_whitespace(str8_cstring_capped(header->user_id, header->user_id + sizeof(header->user_id) )); + String8 group_id = str8_skip_chop_whitespace(str8_cstring_capped(header->group_id, header->group_id + sizeof(header->group_id))); + String8 mode = str8_skip_chop_whitespace(str8_cstring_capped(header->mode, header->mode + sizeof(header->mode) )); + String8 size = str8_skip_chop_whitespace(str8_cstring_capped(header->size, header->size + sizeof(header->size) )); + String8 end = str8_cstring_capped(header->end, header->end + sizeof(header->end)); + + U32 data_size = u32_from_str8(size, 10); + U64 data_off = offset + sizeof(COFF_ArchiveMemberHeader); + + header_out->name = name; + header_out->time_stamp = u32_from_str8(date, 10); + header_out->user_id = u32_from_str8(user_id, 10); + header_out->group_id = u32_from_str8(group_id, 10); + header_out->mode = mode; + header_out->is_end_correct = str8_match_lit("`\n", end, 0); + header_out->data_range = rng_1u64(data_off, data_off + data_size); + + return sizeof(*header); + } + return 0; +} + +internal COFF_ArchiveFirstMember +coff_parse_first_archive_member(COFF_ArchiveMember *member) +{ + Assert(str8_match_lit("/", member->header.name, 0)); + + U64 cursor = 0; + + U32 symbol_count = 0; + cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); + + symbol_count = from_be_u32(symbol_count); + + Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U32)); + cursor += dim_1u64(member_offsets_range); + + Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); + cursor += dim_1u64(string_table_range); + + String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); + U32 *member_offsets = (U32 *)raw_member_offsets.str; + U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); + + COFF_ArchiveFirstMember result = {0}; + result.symbol_count = symbol_count; + result.member_offset_count = member_offset_count; + result.member_offsets = member_offsets; + result.string_table = str8_substr(member->data, string_table_range); + + return result; +} + +internal COFF_ArchiveSecondMember +coff_parse_second_archive_member(COFF_ArchiveMember *member) +{ + COFF_ArchiveSecondMember result = {0}; + + if (str8_match_lit("/", member->header.name, 0)) { + U64 cursor = 0; + + U32 member_count = 0; + cursor += str8_deserial_read_struct(member->data, cursor, &member_count); + + Rng1U64 member_offsets_range = rng_1u64(cursor, cursor + member_count * sizeof(U32)); + cursor += dim_1u64(member_offsets_range); + + U32 symbol_count = 0; + cursor += str8_deserial_read_struct(member->data, cursor, &symbol_count); + + Rng1U64 symbol_indices_range = rng_1u64(cursor, cursor + symbol_count * sizeof(U16)); + cursor += dim_1u64(symbol_indices_range); + + Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); + + String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); + String8 raw_indices = str8_substr(member->data, symbol_indices_range); + + U32 *member_offsets = (U32 *)raw_member_offsets.str; + U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); + + U16 *symbol_indices = (U16 *)raw_indices.str; + U64 symbol_index_count = raw_indices.size / sizeof(symbol_indices[0]); + + result.member_count = member_count; + result.symbol_count = symbol_count; + result.member_offsets = member_offsets; + result.member_offset_count = member_offset_count; + result.symbol_indices = symbol_indices; + result.symbol_index_count = symbol_index_count; + result.string_table = str8_substr(member->data, string_table_range); + } + + return result; +} + +internal String8 +coff_parse_long_name(String8 long_names, String8 name) +{ + String8 result = name; + if (name.size > 0 && name.str[0] == '/') { + String8 offset_str = str8(name.str + 1, name.size - 1); + U64 offset = u64_from_str8(offset_str, 10); + if (offset < long_names.size) { + U8 *ptr = long_names.str + offset; + U8 *opl = long_names.str + long_names.size; + for (; ptr < opl; ++ptr) { + if (*ptr == '\0' || *ptr == '\n') { + break; + } + } + result = str8_range(long_names.str + offset, ptr); + } + } + return result; +} + +internal U64 +coff_parse_import(String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImportHeader *header_out) +{ + COFF_ImportHeader *header = str8_deserial_get_raw_ptr(raw_archive_member, offset, sizeof(*header)); + if (header) { + Rng1U64 data_range = rng_1u64(offset + sizeof(*header), offset + sizeof(*header) + header->data_size); + String8 raw_data = str8_substr(raw_archive_member, data_range); + U64 data_cursor = 0; + + header_out->version = header->version; + header_out->machine = header->machine; + header_out->time_stamp = header->time_stamp; + header_out->data_size = header->data_size; + header_out->hint_or_ordinal = header->hint_or_ordinal; + header_out->type = COFF_ImportHeader_ExtractType(header->flags); + header_out->import_by = COFF_ImportHeader_ExtractImportBy(header->flags); + data_cursor += str8_deserial_read_cstr(raw_data, data_cursor, &header_out->func_name); + data_cursor += str8_deserial_read_cstr(raw_data, data_cursor, &header_out->dll_name); + + Assert(header_out->func_name.size + header_out->dll_name.size + /* nulls */ 2 == header_out->data_size); + U64 read_size = sizeof(*header) + header->data_size; + return read_size; + } + return 0; +} + +internal COFF_ArchiveMember +coff_archive_member_from_offset(String8 raw_archive, U64 offset) +{ + COFF_ArchiveMember member = {0}; + coff_regular_archive_member_iter_next(raw_archive, &offset, &member); + return member; +} + +internal COFF_ArchiveMember +coff_archive_member_from_data(String8 raw_archive_member) +{ + return coff_archive_member_from_offset(raw_archive_member, 0); +} + +internal COFF_ParsedArchiveImportHeader +coff_archive_import_from_data(String8 raw_archive_member) +{ + COFF_ParsedArchiveImportHeader header = {0}; + coff_parse_import(raw_archive_member, 0, &header); + return header; +} + +internal U64 +coff_regular_archive_member_iter_init(String8 raw_archive) +{ + U64 cursor = raw_archive.size; + if (coff_is_regular_archive(raw_archive)) { + cursor = sizeof(g_coff_archive_sig); + } + return cursor; +} + +internal B32 +coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out) +{ + B32 is_parsed = 0; + + member_out->header.is_end_correct = 0; + U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header); + + if (member_out->header.is_end_correct) { + member_out->offset = *offset; + member_out->data = str8_substr(raw_archive, member_out->header.data_range); + + U64 read_size = AlignPow2(header_size + dim_1u64(member_out->header.data_range), COFF_Archive_MemberAlign); + *offset += read_size; + + is_parsed = 1; + } + + return is_parsed; +} + +internal U64 +coff_thin_archive_member_iter_init(String8 raw_archive) +{ + U64 cursor = raw_archive.size; + if (coff_is_thin_archive(raw_archive)) { + cursor = sizeof(g_coff_thin_archive_sig); + } + return cursor; +} + +internal B32 +coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out) +{ + B32 is_parsed = 0; + + member_out->header.is_end_correct = 0; + U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header); + + if (member_out->header.is_end_correct) { + Rng1U64 data_in_archive_range = {0}; + if (str8_match_lit("/", member_out->header.name, 0) || str8_match_lit("//", member_out->header.name, 0)) { + data_in_archive_range = member_out->header.data_range; + } + + member_out->offset = *offset; + member_out->data = str8_substr(raw_archive, data_in_archive_range); + + U64 read_size = AlignPow2(header_size + dim_1u64(data_in_archive_range), COFF_Archive_MemberAlign); + *offset += read_size; + + is_parsed = 1; + } + + return is_parsed; +} + +internal void +coff_archive_member_list_push_node(COFF_ArchiveMemberList *list, COFF_ArchiveMemberNode *node) +{ + SLLQueuePush(list->first, list->last, node); + list->count += 1; +} + +internal COFF_ArchiveParse +coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) +{ + String8 error = str8_zero(); + B32 has_second_header = 0; + B32 has_long_names = 0; + COFF_ArchiveMember first_header = {0}; + COFF_ArchiveMember second_header = {0}; + COFF_ArchiveMember long_names_member = {0}; + + COFF_ArchiveMemberNode *ptr = member_list.first; + + if (ptr) { + if (str8_match_lit("/", ptr->data.header.name, 0)) { + if (ptr->data.header.is_end_correct) { + first_header = ptr->data; + ptr = ptr->next; + } else { + error = str8_lit("first header doesn't have correct end"); + } + } + } else { + error = str8_lit("missing first header"); + } + + if (!error.size && ptr) { + if (str8_match_lit("/", ptr->data.header.name, 0)) { + if (ptr->data.header.is_end_correct) { + second_header = ptr->data; + ptr = ptr->next; + has_second_header = 1; + } else { + error = str8_lit("second header doesn't have correct end"); + } + } + } + + if (!error.size && ptr) { + if (str8_match_lit("//", ptr->data.header.name, 0)) { + if (ptr->data.header.is_end_correct) { + long_names_member = ptr->data; + ptr = ptr->next; + has_long_names; + } else { + error = str8_lit("long names header doesn't have correct end"); + } + } + } + + COFF_ArchiveParse parse = {0}; + parse.has_second_header = has_second_header; + parse.has_long_names = has_long_names; + parse.first_member = coff_parse_first_archive_member(&first_header); + parse.second_member = coff_parse_second_archive_member(&second_header); + parse.long_names = long_names_member.data; + parse.error = error; + + return parse; +} + +internal COFF_ArchiveParse +coff_regular_archive_parse_from_data(String8 raw_archive) +{ + COFF_ArchiveMemberList list = {0}; + COFF_ArchiveMemberNode node_arr[3] = {0}; + U64 cursor = coff_regular_archive_member_iter_init(raw_archive); + for (U64 i = 0; i < ArrayCount(node_arr); ++i) { + COFF_ArchiveMemberNode *node = &node_arr[i]; + if (!coff_regular_archive_member_iter_next(raw_archive, &cursor, &node->data)) { + break; + } + coff_archive_member_list_push_node(&list, node); + } + return coff_archive_parse_from_member_list(list); +} + +internal COFF_ArchiveParse +coff_thin_archive_parse_from_data(String8 raw_archive) +{ + COFF_ArchiveMemberList list = {0}; + COFF_ArchiveMemberNode node_arr[3] = {0}; + U64 cursor = coff_thin_archive_member_iter_init(raw_archive); + for (U64 i = 0; i < ArrayCount(node_arr); i += 1) { + COFF_ArchiveMemberNode *node = &node_arr[i]; + if (!coff_thin_archive_member_iter_next(raw_archive, &cursor, &node->data)) { + break; + } + coff_archive_member_list_push_node(&list, node); + } + return coff_archive_parse_from_member_list(list); +} + +internal COFF_ArchiveParse +coff_archive_parse_from_data(String8 raw_archive) +{ + COFF_ArchiveType type = coff_archive_type_from_data(raw_archive); + switch (type) { + case COFF_Archive_Null: break; + case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive); + case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive); + } + COFF_ArchiveParse null_parse = {0}; + return null_parse; +} + diff --git a/src/coff/coff_parse.h b/src/coff/coff_parse.h new file mode 100644 index 00000000..2ed92e92 --- /dev/null +++ b/src/coff/coff_parse.h @@ -0,0 +1,315 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef COFF_PARSE_H +#define COFF_PARSE_H + +typedef struct COFF_FileHeaderInfo +{ + B32 is_big_obj; + COFF_MachineType machine; + U64 header_size; + U64 section_array_off; + U64 section_count_no_null; + U64 string_table_off; + U64 symbol_size; + U64 symbol_off; + U64 symbol_count; +} COFF_FileHeaderInfo; + +//////////////////////////////// + +typedef struct COFF_SectionHeaderArray +{ + U64 count; + COFF_SectionHeader *v; +} COFF_SectionHeaderArray; + +//////////////////////////////// + +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_ParsedSymbol +{ + String8 name; + U32 value; + U32 section_number; + COFF_SymbolType type; + COFF_SymStorageClass storage_class; + U8 aux_symbol_count; +} COFF_ParsedSymbol; + +typedef U32 COFF_SymbolValueInterpType; +enum +{ + COFF_SymbolValueInterp_Regular, // symbol has section and offset. + COFF_SymbolValueInterp_Weak, // symbol is overridable. + COFF_SymbolValueInterp_Undefined, // symbol doesn't have a reference section. + COFF_SymbolValueInterp_Common, // symbol has no section but still has size. + COFF_SymbolValueInterp_Abs, // symbol has an absolute (non-relocatable) value and is not an address. + COFF_SymbolValueInterp_Debug // symbol is used to provide general type of debugging information. +}; + +//////////////////////////////// + +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 U32 COFF_ResourceIDType; +enum COFF_ResourceIDTypeEnum +{ + COFF_ResourceIDType_Null, + COFF_ResourceIDType_Number, + COFF_ResourceIDType_String, + COFF_ResourceIDType_Count +}; + +typedef struct COFF_ResourceID16 +{ + COFF_ResourceIDType type; + union { + U16 number; + String16 string; + } u; +} COFF_ResourceID16; + +typedef struct COFF_ResourceID +{ + COFF_ResourceIDType type; + union { + U16 number; + String8 string; + } u; +} COFF_ResourceID; + +typedef struct COFF_ParsedResource +{ + COFF_ResourceID type; + COFF_ResourceID name; + U32 data_version; + COFF_ResourceMemoryFlags memory_flags; + U16 language_id; + U32 version; + U32 characteristics; + String8 data; +} COFF_ParsedResource; + +typedef struct COFF_ParsedResourceNode +{ + struct COFF_ParsedResourceNode *next; + COFF_ParsedResource data; +} COFF_ParsedResourceNode; + +typedef struct COFF_ParsedResourceList +{ + U64 count; + COFF_ParsedResourceNode *first; + COFF_ParsedResourceNode *last; +} COFF_ParsedResourceList; + +//////////////////////////////// + +typedef enum +{ + COFF_DataType_Null, + COFF_DataType_Obj, + COFF_DataType_BigObj, + COFF_DataType_Import +} COFF_DataType; + +typedef enum +{ + COFF_Archive_Null, + COFF_Archive_Regular, + COFF_Archive_Thin +} COFF_ArchiveType; + +typedef struct COFF_ParsedArchiveMemberHeader +{ + String8 name; // padded to 16 bytes with spaces + COFF_TimeStamp time_stamp; + 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 + B32 is_end_correct; // set to true if found correct signature after header + Rng1U64 data_range; +} COFF_ParsedArchiveMemberHeader; + +typedef struct COFF_ParsedArchiveImportHeader +{ + B32 is_sig_correct; + U16 version; + COFF_MachineType machine; + COFF_TimeStamp time_stamp; + U32 data_size; + U16 hint_or_ordinal; + COFF_ImportType type; + COFF_ImportByType import_by; + String8 func_name; + String8 dll_name; +} COFF_ParsedArchiveImportHeader; + +typedef struct COFF_ArchiveMember +{ + COFF_ParsedArchiveMemberHeader header; + U64 offset; + String8 data; +} COFF_ArchiveMember; + +typedef struct COFF_ArchiveFirstMember +{ + U32 symbol_count; + U64 member_offset_count; + U32 *member_offsets; + String8 string_table; +} COFF_ArchiveFirstMember; + +typedef struct COFF_ArchiveSecondMember +{ + U32 member_count; + U32 symbol_count; + U64 member_offset_count; + U32 *member_offsets; + U64 symbol_index_count; + U16 *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 struct COFF_ArchiveParse +{ + B32 has_second_header; + B32 has_long_names; + COFF_ArchiveFirstMember first_member; + COFF_ArchiveSecondMember second_member; + String8 long_names; + String8 error; +} COFF_ArchiveParse; + +//////////////////////////////// +// Obj Header + +internal B32 coff_is_big_obj(String8 raw_coff); +internal B32 coff_is_obj (String8 raw_coff); +internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff); + +//////////////////////////////// +// Symbol + +internal COFF_ParsedSymbol coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32); +internal COFF_ParsedSymbol coff_parse_symbol16(String8 raw_coff, U64 string_table_off, 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_array_off, U64 symbol_count, U64 symbol_size); + +internal COFF_Symbol16Node *coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol); + +internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class); + +//////////////////////////////// +// Reloc + +internal COFF_RelocInfo coff_reloc_info_from_section_header(String8 data, COFF_SectionHeader *header); + +//////////////////////////////// +// Resource + +internal String8 coff_resource_string_from_str16 (Arena *arena, String16 string); +internal String8 coff_resource_string_from_str8 (Arena *arena, String8 string); +internal String8 coff_resource_number_from_u16 (Arena *arena, U16 number); +internal COFF_ResourceID coff_utf8_resource_id_from_utf16(Arena *arena, COFF_ResourceID16 *id_16); + +internal U64 coff_read_resource_id_utf16 (String8 raw_res, U64 off, COFF_ResourceID16 *id_out); +internal U64 coff_read_resource (Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *res_out); +internal COFF_ParsedResourceList coff_resource_list_from_data(Arena *arena, String8 data); + +internal String8 coff_write_resource_id(Arena *arena, COFF_ResourceID id); +internal String8 coff_write_resource (Arena *arena, COFF_ResourceID type, COFF_ResourceID name, U32 data_version, COFF_ResourceMemoryFlags memory_flags, U16 language_id, U32 version, U32 characteristics, String8 data); + +internal int coff_resource_id_compar(void *raw_a, void *raw_b); // COFF_ResourceID + +//////////////////////////////// +// Archive + +internal B32 coff_is_import (String8 raw_archive_member); +internal COFF_DataType coff_data_type_from_data (String8 raw_archive_member); +internal B32 coff_is_regular_archive (String8 raw_archive); +internal B32 coff_is_thin_archive (String8 raw_archive); +internal COFF_ArchiveType coff_archive_type_from_data(String8 raw_archive); + +internal U64 coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArchiveMemberHeader *header_out); +internal COFF_ArchiveFirstMember coff_parse_first_archive_member (COFF_ArchiveMember *member); +internal COFF_ArchiveSecondMember coff_parse_second_archive_member(COFF_ArchiveMember *member); +internal String8 coff_parse_long_name (String8 long_names, String8 name); +internal U64 coff_parse_import (String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImportHeader *header_out); + +internal COFF_ArchiveMember coff_archive_member_from_offset(String8 raw_archive, U64 offset); +internal COFF_ArchiveMember coff_archive_member_from_data (String8 raw_archive_member); +internal COFF_ParsedArchiveImportHeader coff_archive_import_from_data (String8 raw_archive_member); + +internal U64 coff_regular_archive_member_iter_init(String8 raw_archive); +internal B32 coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out); + +internal U64 coff_thin_archive_member_iter_init(String8 raw_archive); +internal B32 coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_ArchiveMember *member_out); + +internal COFF_ArchiveParse coff_regular_archive_parse_from_member_list(COFF_ArchiveMemberList list); +internal COFF_ArchiveParse coff_thin_archive_parse_from_data (String8 raw_archive); +internal COFF_ArchiveParse coff_regular_archive_parse_from_data (String8 raw_archive); +internal COFF_ArchiveParse coff_archive_parse_from_data (String8 raw_archive); + +#endif // COFF_PARSE_H diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 41012033..3be0a2fb 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3489,20 +3489,20 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ } //- rjf: read COFF header - U64 coff_header_off = dos_header.coff_file_offset + sizeof(pe_magic); - COFF_Header coff_header = {0}; + U64 file_header_off = dos_header.coff_file_offset + sizeof(pe_magic); + COFF_FileHeader file_header = {0}; if(is_valid) { - if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + coff_header_off, &coff_header)) + if(!dmn_process_read_struct(process.dmn_handle, vaddr_range.min + file_header_off, &file_header)) { is_valid = 0; } } //- rjf: unpack range of optional extension header - U32 opt_ext_size = coff_header.optional_header_size; - Rng1U64 opt_ext_off_range = r1u64(coff_header_off + sizeof(coff_header), - coff_header_off + sizeof(coff_header) + opt_ext_size); + U32 opt_ext_size = file_header.optional_header_size; + Rng1U64 opt_ext_off_range = r1u64(file_header_off + sizeof(COFF_FileHeader), + file_header_off + sizeof(COFF_FileHeader) + opt_ext_size); //- rjf: read optional header U16 optional_magic = 0; @@ -3569,10 +3569,10 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ PE_DataDirectory dir = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_TLS, &dir); Rng1U64 tls_voff_range = r1u64((U64)dir.virt_off, (U64)dir.virt_off + (U64)dir.virt_size); - switch(coff_header.machine) + switch(file_header.machine) { default:{}break; - case COFF_MachineType_X86: + case COFF_Machine_X86: { PE_TLSHeader32 tls_header32 = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + tls_voff_range.min, &tls_header32); @@ -3583,7 +3583,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ tls_header.zero_fill_size = (U64)tls_header32.zero_fill_size; tls_header.characteristics = (U64)tls_header32.characteristics; }break; - case COFF_MachineType_X64: + case COFF_Machine_X64: { dmn_process_read_struct(process.dmn_handle, vaddr_range.min + tls_voff_range.min, &tls_header); }break; diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index d31d029e..1ac146b0 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -469,9 +469,9 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr) } // rjf: get COFF header - B32 got_coff_header = 0; - U64 coff_header_off = 0; - COFF_Header coff_header = {0}; + B32 got_file_header = 0; + U64 file_header_off = 0; + COFF_FileHeader file_header = {0}; if(pe_offset > 0) { U64 pe_magic_off = base_vaddr + pe_offset; @@ -479,28 +479,28 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr) dmn_w32_process_read_struct(process, pe_magic_off, &pe_magic); if(pe_magic == PE_MAGIC) { - coff_header_off = pe_magic_off + sizeof(pe_magic); - if(dmn_w32_process_read_struct(process, coff_header_off, &coff_header)) + file_header_off = pe_magic_off + sizeof(pe_magic); + if(dmn_w32_process_read_struct(process, file_header_off, &file_header)) { - got_coff_header = 1; + got_file_header = 1; } } } // rjf: get arch and size DMN_W32_ImageInfo result = zero_struct; - if(got_coff_header) + if(got_file_header) { U64 optional_size_off = 0; Arch arch = Arch_Null; - switch(coff_header.machine) + switch(file_header.machine) { - case COFF_MachineType_X86: + case COFF_Machine_X86: { arch = Arch_x86; optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image); }break; - case COFF_MachineType_X64: + case COFF_Machine_X64: { arch = Arch_x64; optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image); @@ -510,7 +510,7 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr) } if(arch != Arch_Null) { - U64 optional_off = coff_header_off + sizeof(coff_header); + U64 optional_off = file_header_off + sizeof(COFF_FileHeader); U32 size = 0; if(dmn_w32_process_read_struct(process, optional_off+optional_size_off, &size) >= sizeof(size)) { diff --git a/src/linker/lnk.c b/src/linker/lnk.c index b29c6744..5f74851d 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -36,6 +36,7 @@ #include "path/path.h" #include "coff/coff.h" #include "coff/coff_enum.h" +#include "coff/coff_parse.h" #include "pe/pe.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" @@ -50,6 +51,7 @@ #include "path/path.c" #include "coff/coff.c" #include "coff/coff_enum.c" +#include "coff/coff_parse.c" #include "pe/pe.c" #include "codeview/codeview.c" #include "codeview/codeview_enum.c" @@ -391,8 +393,8 @@ lnk_res_string_id_is_before(void *raw_a, void *raw_b) { PE_Resource *a = raw_a; PE_Resource *b = raw_b; - Assert(a->id.type == COFF_ResourceIDType_STRING); - Assert(b->id.type == COFF_ResourceIDType_STRING); + Assert(a->id.type == COFF_ResourceIDType_String); + Assert(b->id.type == COFF_ResourceIDType_String); int is_before = str8_is_before_case_sensitive(&a->id.u.string, &b->id.u.string); return is_before; } @@ -402,8 +404,8 @@ lnk_res_number_id_is_before(void *raw_a, void *raw_b) { PE_Resource *a = raw_a; PE_Resource *b = raw_b; - Assert(a->id.type == COFF_ResourceIDType_NUMBER); - Assert(b->id.type == COFF_ResourceIDType_NUMBER); + Assert(a->id.type == COFF_ResourceIDType_Number); + Assert(b->id.type == COFF_ResourceIDType_Number); int is_before = u16_is_before(&a->id.u.number, &b->id.u.number); return is_before; } @@ -426,7 +428,7 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE dir_data_chunk->sort_idx = str8_lit("c"); PE_Resource root_wrapper = {0}; - root_wrapper.id.type = COFF_ResourceIDType_NUMBER; + root_wrapper.id.type = COFF_ResourceIDType_Number; root_wrapper.id.u.number = 0; root_wrapper.kind = PE_ResDataKind_DIR; root_wrapper.u.dir = root_dir; @@ -460,11 +462,11 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE stack->coff_entry_chunk = lnk_section_push_chunk_data(dir_sect, stack->coff_entry_array_chunk, str8_struct(entry), str8_zero()); switch (res->id.type) { - case COFF_ResourceIDType_NUMBER: { + case COFF_ResourceIDType_Number: { entry->name.id = res->id.u.number; } break; - case COFF_ResourceIDType_STRING: { + case COFF_ResourceIDType_String: { // TODO: we can make string table smaller by reusing offsets for same strings // not sure why high bit has to be turned on here since number id and string id entries are @@ -480,7 +482,7 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, name.offset), name_symbol); } break; - case COFF_ResourceIDType_NULL: break; + case COFF_ResourceIDType_Null: break; default: InvalidPath; } @@ -499,14 +501,14 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE // push sub directory chunk layout LNK_Chunk *dir_node_chunk = lnk_section_push_chunk_list(dir_sect, dir_tree_chunk, str8_zero()); - dir_node_chunk->align = COFF_RES_ALIGN; + dir_node_chunk->align = COFF_ResourceAlign; LNK_Chunk *dir_header_chunk = lnk_section_push_chunk_data(dir_sect, dir_node_chunk, str8_struct(dir_header), str8_zero()); LNK_Chunk *entry_array_chunk = lnk_section_push_chunk_list(dir_sect, dir_node_chunk, str8_zero()); lnk_chunk_set_debugf(dir_sect->arena, dir_header_chunk, "DIR_HEADER_CHUNK"); lnk_chunk_set_debugf(dir_sect->arena, entry_array_chunk, "DIR_ENTRY_ARRAY_CHUNK"); // push symbols to patch coff entry - LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_RESOURCE_SUB_DIR_FLAG); + LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_Resource_SubDirFlag); LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0); lnk_symbol_table_push(symtab, flag_symbol); // set high bit to indicate directory lnk_symbol_table_push(symtab, offset_symbol); // write offset for this directory @@ -542,8 +544,8 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE LNK_Chunk *resource_data_chunk = lnk_section_push_chunk_data(data_sect, data_sect->root, res->u.coff_res.data, str8_zero()); // windows errors out on unaligned data - coff_resource_data_entry_chunk->align = COFF_RES_ALIGN; - resource_data_chunk->align = COFF_RES_ALIGN; + coff_resource_data_entry_chunk->align = COFF_ResourceAlign; + resource_data_chunk->align = COFF_ResourceAlign; // relocate data String8 resource_data_symbol_name = push_str8f(symtab->arena->v[0], "$R%06X", total_res_count); @@ -725,8 +727,8 @@ lnk_make_res_obj(TP_Context *tp, COFF_Symbol16 coff_feat00 = {0}; MemoryCopyStr8(&coff_feat00.name, str8_lit("@feat.00")); coff_feat00.value = MSCRT_FeatFlag_HAS_SAFE_SEH|MSCRT_FeatFlag_UNKNOWN_4; - coff_feat00.section_number = COFF_SYMBOL_ABS_SECTION_16; - coff_feat00.storage_class = COFF_SymStorageClass_STATIC; + coff_feat00.section_number = COFF_Symbol_AbsSection16; + coff_feat00.storage_class = COFF_SymStorageClass_Static; coff_symbol16_list_push(scratch.arena, &coff_symbol_list, coff_feat00); // emit coff symbols for section definitions @@ -749,7 +751,7 @@ lnk_make_res_obj(TP_Context *tp, coff_sect_symbol.value = 0; coff_sect_symbol.section_number = sect->isect; coff_sect_symbol.aux_symbol_count = 1; - coff_sect_symbol.storage_class = COFF_SymStorageClass_STATIC; + coff_sect_symbol.storage_class = COFF_SymStorageClass_Static; Assert(sect->isect <= max_U16); COFF_SymbolSecDef secdef = {0}; @@ -805,7 +807,7 @@ lnk_make_res_obj(TP_Context *tp, MemoryCopyStr8(&coff_symbol.name, symbol_name); coff_symbol.value = symbol_offset; coff_symbol.section_number = symbol_sect->isect; - coff_symbol.storage_class = COFF_SymStorageClass_STATIC; + coff_symbol.storage_class = COFF_SymStorageClass_Static; coff_symbol16_list_push(scratch.arena, &coff_symbol_list, coff_symbol); // push coff reloc @@ -843,7 +845,7 @@ lnk_make_res_obj(TP_Context *tp, } } - LNK_Section *misc_sect = lnk_section_table_push(st, str8_lit(".misc"), COFF_SectionFlag_LNK_INFO|COFF_SectionFlag_LNK_REMOVE); + LNK_Section *misc_sect = lnk_section_table_push(st, str8_lit(".misc"), COFF_SectionFlag_LnkInfo|COFF_SectionFlag_LnkRemove); misc_sect->emit_header = 0; // serialize coff symbol list @@ -863,27 +865,27 @@ lnk_make_res_obj(TP_Context *tp, // build obj header { // init header - COFF_Header *coff_header = push_array(header_sect->arena, COFF_Header, 1); - coff_header->machine = machine; - coff_header->section_count = 0; // relocated - coff_header->time_stamp = time_stamp; - coff_header->symbol_table_foff = 0; // relocated - coff_header->symbol_count = 0; // relocated - coff_header->optional_header_size = 0; // no PE header in obj - coff_header->flags = COFF_Flag_32BIT_MACHINE; + COFF_FileHeader *file_header = push_array(header_sect->arena, COFF_FileHeader, 1); + file_header->machine = machine; + file_header->section_count = 0; // relocated + file_header->time_stamp = time_stamp; + file_header->symbol_table_foff = 0; // relocated + file_header->symbol_count = 0; // relocated + file_header->optional_header_size = 0; // no PE header in obj + file_header->flags = COFF_FileHeaderFlag_32BitMachine; // push coff header chunk - String8 coff_header_data = str8_struct(coff_header); - LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_data(header_sect, header_sect->root, coff_header_data, str8_zero()); + String8 file_header_data = str8_struct(file_header); + LNK_Chunk *file_header_chunk = lnk_section_push_chunk_data(header_sect, header_sect->root, file_header_data, str8_zero()); // relocate coff header fields - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); - lnk_section_push_reloc(header_sect, coff_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_Header, symbol_table_foff), coff_symbol_table_symbol); - lnk_section_push_reloc(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, symbol_count), coff_symbol_count_symbol); + lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_FileHeader, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc(header_sect, file_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_FileHeader, symbol_table_foff), coff_symbol_table_symbol); + lnk_section_push_reloc(header_sect, file_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_FileHeader, symbol_count), coff_symbol_count_symbol); // push coff header symbol - LNK_Symbol *coff_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, coff_header_symbol); + LNK_Symbol *file_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit(LNK_COFF_FILE_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0); + lnk_symbol_table_push(symtab, file_header_symbol); } // build section headers @@ -923,7 +925,7 @@ lnk_make_res_obj(TP_Context *tp, } // patch file fields - if (~sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { LNK_Symbol *sect_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, sect->name); lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(COFF_SectionHeader, fsize), sect_symbol); lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, foff), sect_symbol); @@ -1034,13 +1036,13 @@ lnk_make_linker_coff_obj(TP_Context *tp, header_sect->emit_header = 0; { - COFF_Header *coff_header = push_array(header_sect->arena, COFF_Header, 1); - coff_header->machine = machine; - coff_header->section_count = 0; - coff_header->time_stamp = time_stamp; + COFF_FileHeader *file_header = push_array(header_sect->arena, COFF_FileHeader, 1); + file_header->machine = machine; + file_header->section_count = 0; + file_header->time_stamp = time_stamp; - LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, header_sect->root, coff_header, sizeof(*coff_header), str8_zero()); - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); + LNK_Chunk *file_header_chunk = lnk_section_push_chunk_raw(header_sect, header_sect->root, file_header, sizeof(*file_header), str8_zero()); + lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_FileHeader, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); } { @@ -1139,7 +1141,7 @@ lnk_make_linker_coff_obj(TP_Context *tp, } // emit relocs for file fields - if (~sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { LNK_Symbol *sect_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, sect->name); lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(COFF_SectionHeader, fsize), sect_symbol); lnk_section_push_reloc(header_sect, coff_sect_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, foff), sect_symbol); @@ -1232,12 +1234,12 @@ lnk_push_input_from_lazy(Arena *arena, PathStyle path_style, LNK_LazySymbol *laz COFF_DataType member_type = coff_data_type_from_data(member_info.data); switch (member_type) { - case COFF_DataType_IMPORT: { + case COFF_DataType_Import: { LNK_InputImport *input = lnk_input_import_list_push(arena, input_import_list); input->import_header = coff_archive_import_from_data(member_info.data); } break; - case COFF_DataType_BIG_OBJ: - case COFF_DataType_OBJ: { + case COFF_DataType_BigObj: + case COFF_DataType_Obj: { String8 obj_path = coff_parse_long_name(lazy->lib->long_names, member_info.header.name); // obj path in thin archive has slash appended which screws up @@ -1279,12 +1281,12 @@ lnk_push_linker_symbols(LNK_SymbolTable *symtab, COFF_MachineType machine) // passing it around as a function argument. // // 100h: lea rax, [rip + ffffff00h] ; -100h - LNK_Symbol *image_base = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("__ImageBase"), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_ANY, 0); + LNK_Symbol *image_base = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("__ImageBase"), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelect_Any, 0); { // load config symbols - if (machine == COFF_MachineType_X86) { - lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); - lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); + if (machine == COFF_Machine_X86) { + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelect_NoDuplicates, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelect_NoDuplicates, 0); } // TODO: investigate IMAGE_ENCLAVE_CONFIG 32/64 @@ -1409,7 +1411,7 @@ lnk_build_debug_rdi(LNK_SectionTable *st, { ProfBeginFunction(); - LNK_Section *rdi_sect = lnk_section_table_push(st, str8_lit(".raddbg"), COFF_SectionFlag_CNT_INITIALIZED_DATA|COFF_SectionFlag_MEM_READ); + LNK_Section *rdi_sect = lnk_section_table_push(st, str8_lit(".raddbg"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead); // push chunks String8 debug_rdi = pe_make_debug_header_rdi(rdi_sect->arena, guid, rdi_path); @@ -1488,7 +1490,7 @@ lnk_build_guard_tables(TP_Context *tp, if (lnk_chunk_is_discarded(chunk)) { continue; } - if (~chunk->flags & COFF_SectionFlag_CNT_CODE) { + if (~chunk->flags & COFF_SectionFlag_CntCode) { continue; } Assert(chunk->type == LNK_Chunk_Leaf); @@ -1508,7 +1510,7 @@ lnk_build_guard_tables(TP_Context *tp, if (symbol_chunk->type != LNK_Chunk_Leaf) { continue; } - if (~symbol_chunk->flags & COFF_SectionFlag_CNT_CODE) { + if (~symbol_chunk->flags & COFF_SectionFlag_CntCode) { continue; } lnk_symbol_list_push(scratch.arena, &guard_symbol_list_table[GUARD_FIDS], symbol); @@ -1603,7 +1605,7 @@ lnk_build_guard_tables(TP_Context *tp, } // TODO: emit table for SEH on X86 - if (machine == COFF_MachineType_X86) { + if (machine == COFF_Machine_X86) { lnk_not_implemented("__safe_se_handler_table"); lnk_not_implemented("__safe_se_handler_count"); } @@ -2078,7 +2080,7 @@ internal LNK_Chunk * lnk_build_coff_file_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chunk *parent, COFF_MachineType machine, COFF_TimeStamp time_stamp, PE_ImageFileCharacteristics file_characteristics) { - COFF_Header *file_header = push_array_no_zero(header_sect->arena, COFF_Header, 1); + COFF_FileHeader *file_header = push_array_no_zero(header_sect->arena, COFF_FileHeader, 1); file_header->machine = machine; file_header->time_stamp = time_stamp; file_header->symbol_table_foff = 0; @@ -2088,16 +2090,16 @@ lnk_build_coff_file_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LN file_header->flags = file_characteristics; LNK_Chunk *file_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, file_header, sizeof(*file_header), str8_zero()); - lnk_chunk_set_debugf(header_sect->arena, file_header_chunk, LNK_COFF_HEADER_SYMBOL_NAME); + lnk_chunk_set_debugf(header_sect->arena, file_header_chunk, LNK_COFF_FILE_HEADER_SYMBOL_NAME); - lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_FILE_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0); // :section_count - lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_16, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_16, OffsetOf(COFF_FileHeader, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); // :optional_header_size - lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_16, OffsetOf(COFF_Header, optional_header_size), str8_lit(LNK_PE_OPT_HEADER_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); - lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_16, OffsetOf(COFF_Header, optional_header_size), str8_lit(LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_16, OffsetOf(COFF_FileHeader, optional_header_size), str8_lit(LNK_PE_OPT_HEADER_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_16, OffsetOf(COFF_FileHeader, optional_header_size), str8_lit(LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); return file_header_chunk; } @@ -2173,17 +2175,17 @@ lnk_build_pe_optional_header_x64(LNK_SymbolTable *symtab, continue; } // :sizeof_uninited_data - if (sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (sect->flags & COFF_SectionFlag_CntUninitializedData) { lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_CHUNK_SIZE_VIRT_32, OffsetOf(PE_OptionalHeader32Plus, sizeof_uninited_data), sect->name, LNK_SymbolScopeFlag_Internal); } // :sizeof_inited_data - if (sect->flags & COFF_SectionFlag_CNT_INITIALIZED_DATA) { + if (sect->flags & COFF_SectionFlag_CntInitializedData) { lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(PE_OptionalHeader32Plus, sizeof_inited_data), sect->name, LNK_SymbolScopeFlag_Internal); } // :sizeof_code - if (sect->flags & COFF_SectionFlag_CNT_CODE) { + if (sect->flags & COFF_SectionFlag_CntCode) { lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(PE_OptionalHeader32Plus, sizeof_code), sect->name, LNK_SymbolScopeFlag_Internal); } @@ -2202,7 +2204,7 @@ lnk_build_pe_optional_header_x64(LNK_SymbolTable *symtab, lnk_section_push_reloc(header_sect, opt_header_chunk, LNK_Reloc_FILE_ALIGN_32, OffsetOf(PE_OptionalHeader32Plus, sizeof_headers), &g_null_symbol); // :check_sum - lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_CHECKSUM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, OffsetOf(PE_OptionalHeader32Plus, check_sum), COFF_ComdatSelectType_NODUPLICATES, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_CHECKSUM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, OffsetOf(PE_OptionalHeader32Plus, check_sum), COFF_ComdatSelect_NoDuplicates, 0); // :data_dir_count lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(PE_OptionalHeader32Plus, data_dir_count), str8_lit(LNK_PE_DIRECTORY_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); @@ -2272,11 +2274,11 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, } // push COFF header array chunk - LNK_Chunk *coff_header_array_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8_zero()); - lnk_chunk_set_debugf(header_sect->arena, coff_header_array_chunk, LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME); + LNK_Chunk *COFF_FileHeader_array_chunk = lnk_section_push_chunk_list(header_sect, parent_chunk, str8_zero()); + lnk_chunk_set_debugf(header_sect->arena, COFF_FileHeader_array_chunk, LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME); // define symbol for COFF header array - lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_array_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, COFF_FileHeader_array_chunk, 0, 0, 0); // push headers for (LNK_Section *sect = §_arr.v[0], *sect_opl = sect + sect_arr.count; sect < sect_opl; sect += 1) { @@ -2286,38 +2288,38 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, if (!sect->has_layout) { continue; } - COFF_SectionHeader *coff_header = push_array_no_zero(header_sect->arena, COFF_SectionHeader, 1); + COFF_SectionHeader *COFF_FileHeader = push_array_no_zero(header_sect->arena, COFF_SectionHeader, 1); // TODO: for objs we can store long name in string table and write here /offset - if (sect->name.size > sizeof(coff_header->name)) { + if (sect->name.size > sizeof(COFF_FileHeader->name)) { lnk_error(LNK_Warning_LongSectionName, "not enough space in COFF section header to store entire name \"%S\"", sect->name); } - MemorySet(&coff_header->name[0], 0, sizeof(coff_header->name)); - MemoryCopy(&coff_header->name[0], sect->name.str, Min(sect->name.size, sizeof(coff_header->name))); - coff_header->vsize = 0; // :vsize - coff_header->voff = 0; // :voff - coff_header->fsize = 0; // :fsize - coff_header->foff = 0; // :foff - coff_header->relocs_foff = 0; // :relocs_foff - coff_header->lines_foff = 0; // obsolete - coff_header->reloc_count = 0; // :reloc_count - coff_header->line_count = 0; // obsolete - coff_header->flags = sect->flags; + MemorySet(&COFF_FileHeader->name[0], 0, sizeof(COFF_FileHeader->name)); + MemoryCopy(&COFF_FileHeader->name[0], sect->name.str, Min(sect->name.size, sizeof(COFF_FileHeader->name))); + COFF_FileHeader->vsize = 0; // :vsize + COFF_FileHeader->voff = 0; // :voff + COFF_FileHeader->fsize = 0; // :fsize + COFF_FileHeader->foff = 0; // :foff + COFF_FileHeader->relocs_foff = 0; // :relocs_foff + COFF_FileHeader->lines_foff = 0; // obsolete + COFF_FileHeader->reloc_count = 0; // :reloc_count + COFF_FileHeader->line_count = 0; // obsolete + COFF_FileHeader->flags = sect->flags; // push chunk - LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, coff_header_array_chunk, coff_header, sizeof(*coff_header), str8_zero()); + LNK_Chunk *COFF_FileHeader_chunk = lnk_section_push_chunk_raw(header_sect, COFF_FileHeader_array_chunk, COFF_FileHeader, sizeof(*COFF_FileHeader), str8_zero()); // :vsize - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_CHUNK_SIZE_VIRT_32, OffsetOf(COFF_SectionHeader, vsize), sect->name, LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, COFF_FileHeader_chunk, LNK_Reloc_CHUNK_SIZE_VIRT_32, OffsetOf(COFF_SectionHeader, vsize), sect->name, LNK_SymbolScopeFlag_Internal); // :voff - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_SectionHeader, voff), sect->name, LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, COFF_FileHeader_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_SectionHeader, voff), sect->name, LNK_SymbolScopeFlag_Internal); - if (~sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { // :fsize - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(COFF_SectionHeader, fsize), sect->name, LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, COFF_FileHeader_chunk, LNK_Reloc_CHUNK_SIZE_FILE_32, OffsetOf(COFF_SectionHeader, fsize), sect->name, LNK_SymbolScopeFlag_Internal); // :foff - lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, foff), sect->name, LNK_SymbolScopeFlag_Internal); + lnk_section_push_reloc_undefined(header_sect, COFF_FileHeader_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(COFF_SectionHeader, foff), sect->name, LNK_SymbolScopeFlag_Internal); } // TODO: :reloc_off @@ -2325,10 +2327,10 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, } // push symbol for section header count - U64 header_count = coff_header_array_chunk->u.list->count; + U64 header_count = COFF_FileHeader_array_chunk->u.list->count; lnk_symbol_table_push_defined_va(symtab, str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, header_count); - return coff_header_array_chunk; + return COFF_FileHeader_array_chunk; } internal LNK_Chunk * @@ -2371,7 +2373,7 @@ lnk_build_win32_image_header(LNK_SymbolTable *symtab, lnk_build_pe_magic(symtab, header_sect, pe_magic_chunk); lnk_build_coff_file_header(symtab, header_sect, coff_file_header_chunk, config->machine, config->time_stamp, config->file_characteristics); switch (config->machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { lnk_build_pe_optional_header_x64(symtab, header_sect, pe_optional_chunk, @@ -2455,13 +2457,13 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder) LNK_Symbol *lazy = 0; switch (weak->lookup_type) { - case COFF_WeakExtType_NOLIBRARY: { + case COFF_WeakExt_NoLibrary: { // NOLIBRARY means weak symbol should be resolved in case where strong definition pulls in lib member. } break; - case COFF_WeakExtType_SEARCH_LIBRARY: { + case COFF_WeakExt_SearchLibrary: { lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); } break; - case COFF_WeakExtType_SEARCH_ALIAS: { + case COFF_WeakExt_SearchAlias: { lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); if (!lazy) { if (str8_match_lit(".weak.", symbol->name, StringMatchFlag_RightSideSloppy)) { @@ -2964,9 +2966,9 @@ lnk_log_size_breakdown(LNK_SectionTable *st, LNK_SymbolTable *symtab) LNK_Section *sect = §_node->data; if (sect->has_layout) { U64 sect_size = lnk_file_size_from_chunk_ref(sect_id_map, sect->root->ref); - if (sect->flags & COFF_SectionFlag_CNT_CODE) { + if (sect->flags & COFF_SectionFlag_CntCode) { code_size += sect_size; - } else if (sect->flags & COFF_SectionFlag_CNT_INITIALIZED_DATA) { + } else if (sect->flags & COFF_SectionFlag_CntInitializedData) { data_size += sect_size; } } @@ -2974,21 +2976,21 @@ lnk_log_size_breakdown(LNK_SectionTable *st, LNK_SymbolTable *symtab) LNK_Symbol *dos_header_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_DOS_HEADER_SYMBOL_NAME)); LNK_Symbol *dos_program_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_DOS_PROGRAM_SYMBOL_NAME)); - LNK_Symbol *coff_header_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME)); + LNK_Symbol *COFF_FileHeader_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_COFF_FILE_HEADER_SYMBOL_NAME)); LNK_Symbol *coff_section_header_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME)); LNK_Symbol *pe_opt_header_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_PE_OPT_HEADER_SYMBOL_NAME)); LNK_Symbol *pe_directories_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Internal, str8_lit(LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME)); LNK_Chunk *dos_header_chunk = dos_header_symbol->u.defined.u.chunk; LNK_Chunk *dos_program_chunk = dos_program_symbol->u.defined.u.chunk; - LNK_Chunk *coff_header_chunk = coff_header_symbol->u.defined.u.chunk; + LNK_Chunk *COFF_FileHeader_chunk = COFF_FileHeader_symbol->u.defined.u.chunk; LNK_Chunk *coff_section_header_chunk = coff_section_header_symbol->u.defined.u.chunk; LNK_Chunk *pe_opt_header_chunk = pe_opt_header_symbol->u.defined.u.chunk; LNK_Chunk *pe_directories_chunk = pe_directories_symbol->u.defined.u.chunk; U64 dos_header_size = lnk_file_size_from_chunk_ref(sect_id_map, dos_header_chunk->ref); U64 dos_program_size = lnk_file_size_from_chunk_ref(sect_id_map, dos_program_chunk->ref); - U64 coff_header_size = lnk_file_size_from_chunk_ref(sect_id_map, coff_header_chunk->ref); + U64 COFF_FileHeader_size = lnk_file_size_from_chunk_ref(sect_id_map, COFF_FileHeader_chunk->ref); U64 coff_section_header_size = lnk_file_size_from_chunk_ref(sect_id_map, coff_section_header_chunk->ref); U64 pe_opt_header_size = lnk_file_size_from_chunk_ref(sect_id_map, pe_opt_header_chunk->ref); U64 pe_directories_size = lnk_file_size_from_chunk_ref(sect_id_map, pe_directories_chunk->ref); @@ -2997,7 +2999,7 @@ lnk_log_size_breakdown(LNK_SectionTable *st, LNK_SymbolTable *symtab) str8_list_pushf(scratch.arena, &output_list, "--- Image Size Breakdown -------------------------------------------------------"); str8_list_pushf(scratch.arena, &output_list, " DOS Header: %M", dos_header_size); str8_list_pushf(scratch.arena, &output_list, " DOS Program Stub: %M", dos_program_size); - str8_list_pushf(scratch.arena, &output_list, " COFF Header: %M", coff_header_size); + str8_list_pushf(scratch.arena, &output_list, " COFF Header: %M", COFF_FileHeader_size); str8_list_pushf(scratch.arena, &output_list, " COFF Section Headers: %M", coff_section_header_size); str8_list_pushf(scratch.arena, &output_list, " PE Header: %M", pe_opt_header_size); str8_list_pushf(scratch.arena, &output_list, " Directories: %M", pe_directories_size); @@ -3403,8 +3405,8 @@ lnk_run(int argc, char **argv) String8 delay_helper_name = str8_zero(); switch (config->machine) { - case COFF_MachineType_X86: delay_helper_name = str8_cstring(LNK_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME); break; - case COFF_MachineType_X64: delay_helper_name = str8_cstring(LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME); break; + case COFF_Machine_X86: delay_helper_name = str8_cstring(LNK_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME); break; + case COFF_Machine_X64: delay_helper_name = str8_cstring(LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME); break; default: NotImplemented; } @@ -3438,7 +3440,7 @@ lnk_run(int argc, char **argv) for (String8Node *from_node = alt_name_list.from_list.first, *to_node = alt_name_list.to_list.first; from_node != 0; from_node = from_node->next, to_node = to_node->next) { - LNK_Symbol *weak = lnk_symbol_table_push_weak(symtab, from_node->string, COFF_WeakExtType_SEARCH_ALIAS, to_node->string); + LNK_Symbol *weak = lnk_symbol_table_push_weak(symtab, from_node->string, COFF_WeakExt_SearchAlias, to_node->string); lnk_symbol_list_push(scratch.arena, &input_weak_list, weak); } ProfEnd(); @@ -3458,12 +3460,12 @@ lnk_run(int argc, char **argv) case State_InputImports: { ProfBegin("Input Imports"); for (LNK_InputImport *input = input_import_list.first; input != 0; input = input->next) { - COFF_ImportHeader *import_header = &input->import_header; + COFF_ParsedArchiveImportHeader *import_header = &input->import_header; KeyValuePair *is_delayed = hash_table_search_path(delay_load_dll_ht, import_header->dll_name); if (is_delayed) { if (!imptab_delayed) { - Assert(config->machine != COFF_MachineType_UNKNOWN); + Assert(config->machine != COFF_Machine_Unknown); B32 is_unloadable = !!(config->flags & LNK_ConfigFlag_DelayUnload); B32 is_bindable = !!(config->flags & LNK_ConfigFlag_DelayBind); imptab_delayed = lnk_import_table_alloc_delayed(st, symtab, config->machine, is_unloadable, is_bindable); @@ -3478,7 +3480,7 @@ lnk_run(int argc, char **argv) } } else { if (!imptab_static) { - Assert(config->machine != COFF_MachineType_UNKNOWN); + Assert(config->machine != COFF_Machine_Unknown); imptab_static = lnk_import_table_alloc_static(st, symtab, config->machine); } LNK_ImportDLL *dll = lnk_import_table_search_dll(imptab_static, import_header->dll_name); @@ -3560,14 +3562,14 @@ lnk_run(int argc, char **argv) LNK_Obj *obj = &obj_node_arr.v[obj_idx].data; // derive machine from obj - if (config->machine == COFF_MachineType_UNKNOWN) { + if (config->machine == COFF_Machine_Unknown) { config->machine = obj->machine; - } else if (config->machine != COFF_MachineType_X64) { + } else if (config->machine != COFF_Machine_X64) { lnk_error_with_loc(LNK_Error_UnsupportedMachine, obj->path, obj->lib_path, "%S machine is supported", coff_string_from_machine_type(obj->machine)); } else { // is obj machine compatible? if (config->machine != obj->machine && - obj->machine != COFF_MachineType_UNKNOWN) { // obj with unknown machine type is compatible with any other machine type + obj->machine != COFF_Machine_Unknown) { // obj with unknown machine type is compatible with any other machine type lnk_error_obj(LNK_Error_IncompatibleObj, obj, "conflicting machine types expected %S but got %S", coff_string_from_machine_type(config->machine), @@ -3989,18 +3991,18 @@ lnk_run(int argc, char **argv) if (pdata_symbol) { String8 pdata = lnk_data_from_chunk_ref_no_pad(sect_id_map, image_data, pdata_symbol->u.defined.u.chunk->ref); switch (config->machine) { - case COFF_MachineType_X86: - case COFF_MachineType_X64: { + case COFF_Machine_X86: + case COFF_Machine_X64: { U64 count = pdata.size / sizeof(PE_IntelPdata); radsort((PE_IntelPdata *)pdata.str, count, lnk_pdata_is_before_x8664); } break; - case COFF_MachineType_ARM64: - case COFF_MachineType_ARM: { + case COFF_Machine_Arm64: + case COFF_Machine_Arm: { AssertAlways(!"TOOD: ARM"); } break; - case COFF_MachineType_MIPSFPU: - case COFF_MachineType_MIPS16: - case COFF_MachineType_MIPSFPU16: { + case COFF_Machine_MipsFpu: + case COFF_Machine_Mips16: + case COFF_Machine_MipsFpu16: { AssertAlways(!"TODO: MIPS"); } break; } diff --git a/src/linker/lnk.h b/src/linker/lnk.h index a1999a32..9f2b1b35 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -49,7 +49,7 @@ #define LNK_DOS_HEADER_SYMBOL_NAME "DOS_HEADER" #define LNK_DOS_PROGRAM_SYMBOL_NAME "DOS_PROGRAM" #define LNK_PE_MAGIC_SYMBOL_NAME "PE_MAGIC" -#define LNK_COFF_HEADER_SYMBOL_NAME "COFF_HEADER" +#define LNK_COFF_FILE_HEADER_SYMBOL_NAME "COFF_FILE_HEADER" #define LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME "PE_DIRECTORY_ARRAY" #define LNK_PE_DIRECTORY_COUNT_SYMBOL_NAME "PE_DIRECTORY_COUNT" #define LNK_PE_OPT_HEADER_SYMBOL_NAME "PE_OPTIONAL_HEADER" @@ -82,10 +82,10 @@ #define LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME "__delayLoadHelper2" #define LNK_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME "___delayLoadHelper2@8" -#define LNK_TEXT_SECTION_FLAGS (COFF_SectionFlag_CNT_CODE|COFF_SectionFlag_MEM_EXECUTE|COFF_SectionFlag_MEM_READ) -#define LNK_DATA_SECTION_FLAGS (COFF_SectionFlag_CNT_INITIALIZED_DATA|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE) -#define LNK_RDATA_SECTION_FLAGS (COFF_SectionFlag_CNT_INITIALIZED_DATA|COFF_SectionFlag_MEM_READ) -#define LNK_BSS_SECTION_FLAGS (COFF_SectionFlag_CNT_UNINITIALIZED_DATA|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE) +#define LNK_TEXT_SECTION_FLAGS (COFF_SectionFlag_CntCode|COFF_SectionFlag_MemExecute|COFF_SectionFlag_MemRead) +#define LNK_DATA_SECTION_FLAGS (COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite) +#define LNK_RDATA_SECTION_FLAGS (COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead) +#define LNK_BSS_SECTION_FLAGS (COFF_SectionFlag_CntUninitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite) #define LNK_IDATA_SECTION_FLAGS LNK_DATA_SECTION_FLAGS #define LNK_DEBUG_DIR_SECTION_FLAGS LNK_DATA_SECTION_FLAGS #define LNK_RSRC_SECTION_FLAGS LNK_DATA_SECTION_FLAGS @@ -96,8 +96,8 @@ #define LNK_GIATS_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS #define LNK_GLJMP_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS #define LNK_GEHCONT_SECTION_FLAGS LNK_RDATA_SECTION_FLAGS -#define LNK_RELOC_SECTION_FLAGS (LNK_RDATA_SECTION_FLAGS | COFF_SectionFlag_MEM_DISCARDABLE) -#define LNK_DEBUG_SECTION_FLAGS (LNK_RDATA_SECTION_FLAGS | COFF_SectionFlag_MEM_DISCARDABLE) +#define LNK_RELOC_SECTION_FLAGS (LNK_RDATA_SECTION_FLAGS | COFF_SectionFlag_MemDiscardable) +#define LNK_DEBUG_SECTION_FLAGS (LNK_RDATA_SECTION_FLAGS | COFF_SectionFlag_MemDiscardable) //////////////////////////////// @@ -114,7 +114,7 @@ typedef String8List LNK_InputLibList; typedef struct LNK_InputImport { - COFF_ImportHeader import_header; + COFF_ParsedArchiveImportHeader import_header; struct LNK_InputImport *next; } LNK_InputImport; diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index 353068dd..d05e8804 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -352,11 +352,11 @@ lnk_get_default_function_pad_min(COFF_MachineType machine) { U64 function_pad_min = 0; switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: { + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: { function_pad_min = 5; } break; - case COFF_MachineType_X64: { + case COFF_Machine_X64: { function_pad_min = 6; } break; default: { @@ -396,12 +396,12 @@ lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineTyp case PE_WindowsSubsystem_WINDOWS_CUI: { switch (machine) { - case COFF_MachineType_X64: - case COFF_MachineType_X86: ver = make_version(6,0); break; + case COFF_Machine_X64: + case COFF_Machine_X86: ver = make_version(6,0); break; - case COFF_MachineType_ARMNT: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARM: ver = make_version(6,2); break; + case COFF_Machine_ArmNt: + case COFF_Machine_Arm64: + case COFF_Machine_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } @@ -409,12 +409,12 @@ lnk_get_default_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineTyp case PE_WindowsSubsystem_WINDOWS_GUI: { switch (machine) { - case COFF_MachineType_X64: - case COFF_MachineType_X86: ver = make_version(6,0); break; + case COFF_Machine_X64: + case COFF_Machine_X86: ver = make_version(6,0); break; - case COFF_MachineType_ARMNT: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARM: ver = make_version(6,2); break; + case COFF_Machine_ArmNt: + case COFF_Machine_Arm64: + case COFF_Machine_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } @@ -444,13 +444,13 @@ lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType ma case PE_WindowsSubsystem_WINDOWS_CUI: { switch (machine) { - case COFF_MachineType_X86: ver = make_version(5,1); break; + case COFF_Machine_X86: ver = make_version(5,1); break; - case COFF_MachineType_X64: ver = make_version(5,2); break; + case COFF_Machine_X64: ver = make_version(5,2); break; - case COFF_MachineType_ARMNT: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARM: ver = make_version(6,2); break; + case COFF_Machine_ArmNt: + case COFF_Machine_Arm64: + case COFF_Machine_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } @@ -458,13 +458,13 @@ lnk_get_min_subsystem_version(PE_WindowsSubsystem subsystem, COFF_MachineType ma case PE_WindowsSubsystem_WINDOWS_GUI: { switch (machine) { - case COFF_MachineType_X86: ver = make_version(5,1); break; + case COFF_Machine_X86: ver = make_version(5,1); break; - case COFF_MachineType_X64: ver = make_version(5,2); break; + case COFF_Machine_X64: ver = make_version(5,2); break; - case COFF_MachineType_ARMNT: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARM: ver = make_version(6,2); break; + case COFF_Machine_ArmNt: + case COFF_Machine_Arm64: + case COFF_Machine_Arm: ver = make_version(6,2); break; default: lnk_not_implemented("define min subsystem(%S) version for %S", pe_string_from_subsystem(subsystem), coff_string_from_machine_type(machine)); break; } @@ -784,7 +784,7 @@ lnk_parse_export_directive(Arena *arena, LNK_ExportParseList *list, String8List // parse directive String8 name = str8_zero(); String8 alias = str8_zero(); - String8 type = coff_string_from_import_header_type(COFF_ImportHeaderType_CODE); + String8 type = coff_string_from_import_header_type(COFF_ImportHeader_Code); if (value_list.node_count > 0) { String8List dir_split = str8_split_by_string_chars(scratch.arena, value_list.first->string, str8_lit("="), 0); B32 is_export_valid = value_list.node_count <= 2 && value_list.node_count > 0; @@ -1193,7 +1193,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam case LNK_CmdSwitch_Machine: { if (value_strings.node_count == 1) { COFF_MachineType machine = coff_machine_from_string(value_strings.first->string); - if (machine != COFF_MachineType_UNKNOWN) { + if (machine != COFF_Machine_Unknown) { config->machine = machine; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, cmd_switch, "unknown parameter \"%S\"", value_strings.first->string); diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 055ac556..1c175386 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -3025,7 +3025,7 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task) // Mod1::fUpdateSecContrib if (sc_count > 0) { for (U64 sc_idx = 0; sc_idx < sc_count; ++sc_idx) { - if (sc_arr[sc_idx].data.base.flags & COFF_SectionFlag_CNT_CODE) { + if (sc_arr[sc_idx].data.base.flags & COFF_SectionFlag_CntCode) { mod->first_sc = sc_arr[sc_idx].data; break; } diff --git a/src/linker/lnk_export_table.c b/src/linker/lnk_export_table.c index 02bdba68..ff36c649 100644 --- a/src/linker/lnk_export_table.c +++ b/src/linker/lnk_export_table.c @@ -82,22 +82,22 @@ lnk_export_table_push_export(LNK_ExportTable *exptab, LNK_SymbolTable *symtab, L // to CODE instead of DATA. But if you try export global variable with: // #pragma comment(linker, "/export:global_bar,CODE") // MSVC and LLD issue an error. For compatibility sake we do the same thing too. - COFF_ImportHeaderType type = coff_import_header_type_from_string(exp_parse->type); + COFF_ImportType type = coff_import_header_type_from_string(exp_parse->type); switch (type) { - case COFF_ImportHeaderType_CODE: { + case COFF_ImportHeader_Code: { B32 is_export_data = !(def->flags & (LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk)); if (is_export_data) { lnk_error(LNK_Error_IllExport, "export \"%S\" is DATA but has specifier CODE", exp_parse->name); } } break; - case COFF_ImportHeaderType_DATA: { + case COFF_ImportHeader_Data: { B32 is_export_code = !!(def->flags & (LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk)); if (is_export_code) { lnk_error(LNK_Error_IllExport, "export \"%S\" is CODE but has specifier DATA", exp_parse->name); } } break; - case COFF_ImportHeaderType_CONST: { - lnk_not_implemented("TODO: COFF_ImportHeaderType_CONST"); + case COFF_ImportHeader_Const: { + lnk_not_implemented("TODO: COFF_ImportHeader_Const"); } break; default: { if (exp_parse->type.size) { diff --git a/src/linker/lnk_export_table.h b/src/linker/lnk_export_table.h index 15c1205e..25cc31ca 100644 --- a/src/linker/lnk_export_table.h +++ b/src/linker/lnk_export_table.h @@ -5,13 +5,13 @@ typedef struct LNK_Export { - struct LNK_Export *next; - String8 name; - LNK_Symbol *symbol; - U32 id; - U16 ordinal; - COFF_ImportHeaderType type; - B32 is_private; + struct LNK_Export *next; + String8 name; + LNK_Symbol *symbol; + U32 id; + U16 ordinal; + COFF_ImportType type; + B32 is_private; } LNK_Export; typedef struct LNK_ExportList diff --git a/src/linker/lnk_import_table.c b/src/linker/lnk_import_table.c index 616de6fe..34f44e52 100644 --- a/src/linker/lnk_import_table.c +++ b/src/linker/lnk_import_table.c @@ -345,7 +345,7 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt // emit tail merge LNK_Chunk *tail_merge_chunk = 0; switch (machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { LNK_Symbol *delay_load_helper_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], str8_lit(LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME), LNK_SymbolScopeFlag_Main); tail_merge_chunk = lnk_emit_tail_merge_thunk_x64(code_sect, code_chunk, imp_desc_symbol, delay_load_helper_symbol); } break; @@ -375,7 +375,7 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt } internal LNK_ImportFunc * -lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ImportHeader *header) +lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header) { ProfBeginFunction(); @@ -395,20 +395,20 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt U64 import_size = coff_word_size_from_machine(dll->machine); // generate sort index (optional) - String8 sort_index = str8_from_bits_u32(data_sect->arena, header->hint); + String8 sort_index = str8_from_bits_u32(data_sect->arena, header->hint_or_ordinal); - switch (header->name_type) { - case COFF_ImportHeaderNameType_ORDINAL: { - String8 ordinal_data = lnk_ordinal_data_from_hint(data_sect->arena, dll->machine, header->hint); + switch (header->import_by) { + case COFF_ImportBy_Ordinal: { + String8 ordinal_data = lnk_ordinal_data_from_hint(data_sect->arena, dll->machine, header->hint_or_ordinal); ilt_chunk = lnk_section_push_chunk_data(data_sect, ilt_table_chunk, ordinal_data, sort_index); iat_chunk = lnk_section_push_chunk_data(data_sect, iat_table_chunk, ordinal_data, sort_index); // associate chunks lnk_section_associate_chunks(data_sect, iat_chunk, ilt_chunk); } break; - case COFF_ImportHeaderNameType_NAME: { + case COFF_ImportBy_Name: { // put together name look up entry - String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint, header->func_name); + String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint_or_ordinal, header->func_name); LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero()); // create symbol for lookup chunk @@ -429,11 +429,11 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt lnk_section_push_reloc(data_sect, ilt_chunk, LNK_Reloc_VIRT_OFF_32, 0, int_symbol); lnk_section_push_reloc(data_sect, iat_chunk, LNK_Reloc_VIRT_OFF_32, 0, int_symbol); } break; - case COFF_ImportHeaderNameType_UNDECORATE: { - lnk_not_implemented("TODO: COFF_ImportHeaderNameType_UNDECORATE"); + case COFF_ImportBy_Undecorate: { + lnk_not_implemented("TODO: COFF_ImportBy_Undecorate"); } break; - case COFF_ImportHeaderNameType_NAME_NOPREFIX: { - lnk_not_implemented("TODO: COFF_ImportHeaderNameType_NAME_NOPREFIX"); + case COFF_ImportBy_NameNoPrefix: { + lnk_not_implemented("TODO: COFF_ImportBy_NameNoPrefix"); } break; } @@ -444,9 +444,9 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt // generate thunks LNK_Symbol *jmp_thunk_symbol = g_null_symbol_ptr; - if (header->type == COFF_ImportHeaderType_CODE) { + if (header->type == COFF_ImportHeader_Code) { switch (dll->machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { // generate jump thunk LNK_Chunk *jmp_thunk_chunk = lnk_emit_indirect_jump_thunk_x64(code_sect, code_table_chunk, iat_symbol); lnk_section_associate_chunks(data_sect, iat_chunk, jmp_thunk_chunk); @@ -472,7 +472,7 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt } internal LNK_ImportFunc * -lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ImportHeader *header) +lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header) { ProfBeginFunction(); @@ -498,16 +498,16 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym LNK_Symbol *int_symbol = 0; // generate sort index (optional) - String8 sort_index = str8_from_bits_u32(data_sect->arena, header->hint); + String8 sort_index = str8_from_bits_u32(data_sect->arena, header->hint_or_ordinal); // generate thunks LNK_Symbol *jmp_thunk_symbol = g_null_symbol_ptr; LNK_Symbol *load_thunk_symbol = g_null_symbol_ptr; LNK_Chunk *jmp_thunk_chunk = 0; LNK_Chunk *load_thunk_chunk = 0; - if (header->type == COFF_ImportHeaderType_CODE) { + if (header->type == COFF_ImportHeader_Code) { switch (dll->machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name); LNK_Symbol *iat_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], iat_symbol_name, LNK_SymbolScopeFlag_Main); @@ -523,9 +523,9 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym } } - switch (header->name_type) { - case COFF_ImportHeaderNameType_ORDINAL: { - String8 ordinal_data = lnk_ordinal_data_from_hint(data_sect->arena, dll->machine, header->hint); + switch (header->import_by) { + case COFF_ImportBy_Ordinal: { + String8 ordinal_data = lnk_ordinal_data_from_hint(data_sect->arena, dll->machine, header->hint_or_ordinal); Assert(ordinal_data.size == import_size); ilt_chunk = lnk_section_push_chunk_data(data_sect, ilt_table_chunk, ordinal_data, sort_index); iat_chunk = lnk_section_push_chunk_bss(data_sect, iat_table_chunk, import_size, sort_index); @@ -543,9 +543,9 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym lnk_section_associate_chunks(data_sect, iat_chunk, uiat_chunk); } } break; - case COFF_ImportHeaderNameType_NAME: { + case COFF_ImportBy_Name: { // put together name look up entry - String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint, header->func_name); + String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint_or_ordinal, header->func_name); LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero()); // create symbol for lookup chunk @@ -586,11 +586,11 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym lnk_section_push_reloc(data_sect, uiat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol); } } break; - case COFF_ImportHeaderNameType_UNDECORATE: { - lnk_not_implemented("TODO: COFF_ImportHeaderNameType_UNDECORATE"); + case COFF_ImportBy_Undecorate: { + lnk_not_implemented("TODO: COFF_ImportBy_Undecorate"); } break; - case COFF_ImportHeaderNameType_NAME_NOPREFIX: { - lnk_not_implemented("TODO: COFF_ImportHeaderNameType_NAME_NOPREFIX"); + case COFF_ImportBy_NameNoPrefix: { + lnk_not_implemented("TODO: COFF_ImportBy_NameNoPrefix"); } break; } @@ -624,14 +624,14 @@ lnk_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint) { String8 ordinal_data = str8_zero(); switch (machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { U64 *ordinal = push_array(arena, U64, 1); - *ordinal = coff_make_ordinal_64(hint); + *ordinal = coff_make_ordinal64(hint); ordinal_data = str8_struct(ordinal); } break; - case COFF_MachineType_X86: { + case COFF_Machine_X86: { U32 *ordinal = push_array(arena, U32, 1); - *ordinal = coff_make_ordinal_32(hint); + *ordinal = coff_make_ordinal32(hint); ordinal_data = str8_struct(ordinal); } break; default: lnk_not_implemented("TODO: support for machine 0x%x", machine); @@ -736,7 +736,7 @@ lnk_emit_load_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 fu ProfBeginFunction(); // emit load thunk symbol String8 load_thunk_name = push_str8f(symtab->arena->v[0], "__imp_load_%S", func_name); - LNK_Symbol *load_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, load_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelectType_NODUPLICATES, 0); + LNK_Symbol *load_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, load_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelect_NoDuplicates, 0); ProfEnd(); return load_thunk_symbol; } @@ -746,7 +746,7 @@ lnk_emit_jmp_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 fun { ProfBeginFunction(); String8 jmp_thunk_name = push_str8f(symtab->arena->v[0], "%S", func_name); - LNK_Symbol *jmp_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, jmp_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelectType_ANY, 0); + LNK_Symbol *jmp_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, jmp_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelect_Any, 0); ProfEnd(); return jmp_thunk_symbol; } @@ -756,7 +756,7 @@ lnk_emit_tail_merge_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 fu { ProfBeginFunction(); String8 tail_merge_name = push_str8f(symtab->arena->v[0], "__tailMerge_%S", func_name); - LNK_Symbol *tail_merge_symbol = lnk_symbol_table_push_defined_chunk(symtab, tail_merge_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelectType_NODUPLICATES, 0); + LNK_Symbol *tail_merge_symbol = lnk_symbol_table_push_defined_chunk(symtab, tail_merge_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, COFF_ComdatSelect_NoDuplicates, 0); ProfEnd(); return tail_merge_symbol; } diff --git a/src/linker/lnk_import_table.h b/src/linker/lnk_import_table.h index 0299c911..6005b622 100644 --- a/src/linker/lnk_import_table.h +++ b/src/linker/lnk_import_table.h @@ -64,8 +64,8 @@ internal LNK_ImportTable * lnk_import_table_alloc_delayed(LNK_SectionTable *st, internal void lnk_import_table_release(LNK_ImportTable **imptab); internal LNK_ImportDLL * lnk_import_table_push_dll_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, String8 dll_name, COFF_MachineType machine); internal LNK_ImportDLL * lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, String8 dll_name, COFF_MachineType machine); -internal LNK_ImportFunc * lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ImportHeader *header); -internal LNK_ImportFunc * lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ImportHeader *header); +internal LNK_ImportFunc * lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header); +internal LNK_ImportFunc * lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header); internal LNK_ImportDLL * lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 name); internal LNK_ImportFunc * lnk_import_table_search_func(LNK_ImportDLL *dll, String8 name); diff --git a/src/linker/lnk_lib.c b/src/linker/lnk_lib.c index 22225e42..b200b1db 100644 --- a/src/linker/lnk_lib.c +++ b/src/linker/lnk_lib.c @@ -303,19 +303,19 @@ lnk_lib_writer_push_export(LNK_LibWriter *writer, COFF_MachineType machine, U64 lnk_lib_member_list_push(writer->arena, &writer->member_list, member); switch (exp->type) { - case COFF_ImportHeaderType_CODE: { + case COFF_ImportHeader_Code: { LNK_LibSymbol def_symbol = {0}; def_symbol.name = push_str8_copy(writer->arena, exp->name); def_symbol.member_idx = member_idx; lnk_lib_symbol_list_push(writer->arena, &writer->symbol_list, def_symbol); } - case COFF_ImportHeaderType_DATA: { + case COFF_ImportHeader_Data: { LNK_LibSymbol imp_symbol = {0}; imp_symbol.name = push_str8f(writer->arena, "__imp_%S", exp->name); imp_symbol.member_idx = member_idx; lnk_lib_symbol_list_push(writer->arena, &writer->symbol_list, imp_symbol); } break; - case COFF_ImportHeaderType_CONST: { + case COFF_ImportHeader_Const: { NotImplemented; } break; default: InvalidPath; @@ -361,7 +361,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second // make member name String8 name; U64 name_with_slash_size = member->name.size + 1; - if (name_with_slash_size > COFF_ARCHIVE_MAX_SHORT_NAME_SIZE) { + if (name_with_slash_size > COFF_Archive_MaxShortNameSize) { // have we seen this member name before? KeyValuePair *is_present = hash_table_search_string(name_ht, member->name); if (is_present) { @@ -382,7 +382,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second str8_list_push(arena, &member_data_list, member_header); str8_list_push(arena, &member_data_list, member_data); - str8_list_push_pad(arena, &member_data_list, member_data_list.total_size, COFF_ARCHIVE_ALIGN); + str8_list_push_pad(arena, &member_data_list, member_data_list.total_size, COFF_Archive_MemberAlign); } // long names member @@ -390,7 +390,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second String8 header = lnk_build_lib_member_header(arena, str8_lit("//"), time_stamp, 0, 0, mode, long_names_list.total_size); String8 data = str8_list_join(arena, &long_names_list, 0); U64 member_offset = member_data_list.total_size + data.size + header.size; - str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_ARCHIVE_ALIGN); + str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign); str8_list_push_front(arena, &member_data_list, data); str8_list_push_front(arena, &member_data_list, header); } @@ -415,13 +415,13 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second U64 member_base_off; { - U64 sizeof_first_header = COFF_ARCHIVE_MEMBER_HEADER_SIZE + sizeof(U32) + sizeof(U32) * symbol_count + name_buffer_size; - U64 sizeof_second_header = COFF_ARCHIVE_MEMBER_HEADER_SIZE + sizeof(U32) + sizeof(U32) * lib->member_count + sizeof(U32) + sizeof(U16) * symbol_count + name_buffer_size; - U64 sizeof_long_names = COFF_ARCHIVE_MEMBER_HEADER_SIZE + long_names_list.total_size; + U64 sizeof_first_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * symbol_count + name_buffer_size; + U64 sizeof_second_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * lib->member_count + sizeof(U32) + sizeof(U16) * symbol_count + name_buffer_size; + U64 sizeof_long_names = sizeof(COFF_ArchiveMemberHeader) + long_names_list.total_size; - sizeof_first_header = AlignPow2(sizeof_first_header, COFF_ARCHIVE_ALIGN); - sizeof_second_header = AlignPow2(sizeof_second_header, COFF_ARCHIVE_ALIGN); - sizeof_long_names = AlignPow2(sizeof_long_names, COFF_ARCHIVE_ALIGN); + sizeof_first_header = AlignPow2(sizeof_first_header, COFF_Archive_MemberAlign); + sizeof_second_header = AlignPow2(sizeof_second_header, COFF_Archive_MemberAlign); + sizeof_long_names = AlignPow2(sizeof_long_names, COFF_Archive_MemberAlign); member_base_off = sizeof(g_coff_archive_sig); member_base_off += sizeof_first_header; @@ -468,7 +468,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second String8 member_header = lnk_build_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size); U64 member_offset = member_data_list.total_size + member_data.size + member_header.size; - str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_ARCHIVE_ALIGN); + str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign); str8_list_push_front(arena, &member_data_list, member_data); str8_list_push_front(arena, &member_data_list, member_header); } @@ -497,7 +497,7 @@ lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBuild *lib, B32 emit_second String8 member_header = lnk_build_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size); U64 member_offset = sizeof(g_coff_archive_sig) + member_header.size + member_data.size; - str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_ARCHIVE_ALIGN); + str8_list_push_pad_front(arena, &member_data_list, member_offset, COFF_Archive_MemberAlign); str8_list_push_front(arena, &member_data_list, member_data); str8_list_push_front(arena, &member_data_list, member_header); } @@ -541,18 +541,18 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach { ProfBeginFunction(); - Assert(machine == COFF_MachineType_X64); + Assert(machine == COFF_Machine_X64); Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy)); String8List list = {0}; - COFF_Header *coff_header = push_array(arena, COFF_Header, 1); - coff_header->machine = machine; - str8_list_push(arena, &list, str8_struct(coff_header)); + COFF_FileHeader *file_header = push_array(arena, COFF_FileHeader, 1); + file_header->machine = machine; + str8_list_push(arena, &list, str8_struct(file_header)); - coff_header->section_count = 2; - COFF_SectionHeader *coff_sect_header_array = push_array(arena, COFF_SectionHeader, coff_header->section_count); - str8_list_push(arena, &list, str8_array(coff_sect_header_array, coff_header->section_count)); + file_header->section_count = 2; + COFF_SectionHeader *coff_sect_header_array = push_array(arena, COFF_SectionHeader, file_header->section_count); + str8_list_push(arena, &list, str8_array(coff_sect_header_array, file_header->section_count)); PE_ImportEntry *import_entry = push_array(arena, PE_ImportEntry, 1); U64 import_entry_off = list.total_size; @@ -567,10 +567,10 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach U64 import_entry_reloc_off = list.total_size; str8_list_push(arena, &list, str8_array(import_entry_reloc_array, import_entry_reloc_count)); - coff_header->symbol_count = 7; - COFF_Symbol16 *symbol_array = push_array(arena, COFF_Symbol16, coff_header->symbol_count); - coff_header->symbol_table_foff = safe_cast_u32(list.total_size); - str8_list_push(arena, &list, str8_array(symbol_array, coff_header->symbol_count)); + file_header->symbol_count = 7; + COFF_Symbol16 *symbol_array = push_array(arena, COFF_Symbol16, file_header->symbol_count); + file_header->symbol_table_foff = safe_cast_u32(list.total_size); + str8_list_push(arena, &list, str8_array(symbol_array, file_header->symbol_count)); U64 string_table_base = list.total_size; U32 *string_table_size_ptr = push_array(arena, U32, 1); @@ -591,23 +591,23 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach sect->foff = import_entry_off; sect->reloc_count = import_entry_reloc_count; sect->relocs_foff = import_entry_reloc_off; - sect->flags = COFF_SectionFlag_CNT_INITIALIZED_DATA|(COFF_SectionAlign_4BYTES << COFF_SectionFlag_ALIGN_SHIFT)|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE; + sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite; } { COFF_Reloc *lookup_table_voff_reloc = &import_entry_reloc_array[0]; lookup_table_voff_reloc->apply_off = OffsetOf(PE_ImportEntry, lookup_table_voff); lookup_table_voff_reloc->isymbol = 3; - lookup_table_voff_reloc->type = COFF_RelocTypeX64_ADDR32NB; + lookup_table_voff_reloc->type = COFF_Reloc_X64_Addr32Nb; COFF_Reloc *name_voff_reloc = &import_entry_reloc_array[1]; name_voff_reloc->apply_off = OffsetOf(PE_ImportEntry, name_voff); name_voff_reloc->isymbol = 2; - name_voff_reloc->type = COFF_RelocTypeX64_ADDR32NB; + name_voff_reloc->type = COFF_Reloc_X64_Addr32Nb; COFF_Reloc *import_addr_table_voff = &import_entry_reloc_array[2]; import_addr_table_voff->apply_off = OffsetOf(PE_ImportEntry, import_addr_table_voff); import_addr_table_voff->isymbol = 4; - import_addr_table_voff->type = COFF_RelocTypeX64_ADDR32NB; + import_addr_table_voff->type = COFF_Reloc_X64_Addr32Nb; } // dll name @@ -623,7 +623,7 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach sect->name[7] = '6'; sect->fsize = dll_name_cstr.size; sect->foff = dll_name_off; - sect->flags = COFF_SectionFlag_CNT_INITIALIZED_DATA|(COFF_SectionAlign_2BYTES << COFF_SectionFlag_ALIGN_SHIFT)|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE; + sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_2Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite; } // import descriptor @@ -638,7 +638,7 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach symbol->name.long_name.zeroes = 0; symbol->name.long_name.string_table_offset = symbol_name_off; symbol->section_number = 1; - symbol->storage_class = COFF_SymStorageClass_EXTERNAL; + symbol->storage_class = COFF_SymStorageClass_External; } // .idata$2 @@ -653,7 +653,7 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach symbol->name.short_name[6] = '$'; symbol->name.short_name[7] = '2'; symbol->section_number = 1; - symbol->storage_class = COFF_SymStorageClass_SECTION; + symbol->storage_class = COFF_SymStorageClass_Section; } // .idata$6 @@ -668,7 +668,7 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach symbol->name.short_name[6] = '$'; symbol->name.short_name[7] = '6'; symbol->section_number = 2; - symbol->storage_class = COFF_SymStorageClass_STATIC; + symbol->storage_class = COFF_SymStorageClass_Static; } // .idata$4 @@ -682,8 +682,8 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach symbol->name.short_name[5] = 'a'; symbol->name.short_name[6] = '$'; symbol->name.short_name[7] = '4'; - symbol->section_number = COFF_SYMBOL_UNDEFINED_SECTION; - symbol->storage_class = COFF_SymStorageClass_SECTION; + symbol->section_number = COFF_Symbol_UndefinedSection; + symbol->storage_class = COFF_SymStorageClass_Section; } // .idata$5 @@ -697,8 +697,8 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach symbol->name.short_name[5] = 'a'; symbol->name.short_name[6] = '$'; symbol->name.short_name[7] = '5'; - symbol->section_number = COFF_SYMBOL_UNDEFINED_SECTION; - symbol->storage_class = COFF_SymStorageClass_SECTION; + symbol->section_number = COFF_Symbol_UndefinedSection; + symbol->storage_class = COFF_SymStorageClass_Section; } // __NULL_IMPORT_DESCRIPTOR @@ -709,8 +709,8 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach COFF_Symbol16 *symbol = &symbol_array[5]; symbol->name.long_name.zeroes = 0; symbol->name.long_name.string_table_offset = symbol_name_off; - symbol->section_number = COFF_SYMBOL_UNDEFINED_SECTION; - symbol->storage_class = COFF_SymStorageClass_EXTERNAL; + symbol->section_number = COFF_Symbol_UndefinedSection; + symbol->storage_class = COFF_SymStorageClass_External; } // NULL_THUNK_DATA @@ -724,8 +724,8 @@ lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_MachineType mach COFF_Symbol16 *symbol = &symbol_array[6]; symbol->name.long_name.zeroes = 0; symbol->name.long_name.string_table_offset = symbol_name_off; - symbol->section_number = COFF_SYMBOL_UNDEFINED_SECTION; - symbol->storage_class = COFF_SymStorageClass_EXTERNAL; + symbol->section_number = COFF_Symbol_UndefinedSection; + symbol->storage_class = COFF_SymStorageClass_External; } // update string table size @@ -742,7 +742,7 @@ lnk_build_null_import_descriptor_obj(Arena *arena, COFF_MachineType machine) String8List list = {0}; - COFF_Header *coff_header = push_array(arena, COFF_Header, 1); + COFF_FileHeader *coff_header = push_array(arena, COFF_FileHeader, 1); coff_header->machine = machine; str8_list_push(arena, &list, str8_struct(coff_header)); @@ -776,7 +776,7 @@ lnk_build_null_import_descriptor_obj(Arena *arena, COFF_MachineType machine) sect->name[7] = '3'; sect->fsize = null_import_data_size; sect->foff = null_import_data_off; - sect->flags = COFF_SectionFlag_CNT_INITIALIZED_DATA|(COFF_SectionAlign_4BYTES << COFF_SectionFlag_ALIGN_SHIFT)|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE; + sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite; } { @@ -787,7 +787,7 @@ lnk_build_null_import_descriptor_obj(Arena *arena, COFF_MachineType machine) symbol->name.long_name.zeroes = 0; symbol->name.long_name.string_table_offset = symbol_name_off; symbol->section_number = 1; - symbol->storage_class = COFF_SymStorageClass_EXTERNAL; + symbol->storage_class = COFF_SymStorageClass_External; } // update string table size @@ -806,7 +806,7 @@ lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType m String8List list = {0}; - COFF_Header *coff_header = push_array(arena, COFF_Header, 1); + COFF_FileHeader *coff_header = push_array(arena, COFF_FileHeader, 1); coff_header->machine = machine; str8_list_push(arena, &list, str8_struct(coff_header)); @@ -845,7 +845,7 @@ lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType m sect->name[7] = '5'; sect->fsize = lookup_entry_data_size; sect->foff = lookup_entry_data_off; - sect->flags = COFF_SectionFlag_CNT_INITIALIZED_DATA|(COFF_SectionAlign_8BYTES << COFF_SectionFlag_ALIGN_SHIFT)|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE; + sect->flags = COFF_SectionFlag_CntInitializedData | (COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift)|(COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite); } { @@ -860,7 +860,7 @@ lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType m sect->name[7] = '4'; sect->fsize = null_thunk_data_size; sect->foff = null_thunk_data_off; - sect->flags = COFF_SectionFlag_CNT_INITIALIZED_DATA|(COFF_SectionAlign_8BYTES << COFF_SectionFlag_ALIGN_SHIFT)|COFF_SectionFlag_MEM_READ|COFF_SectionFlag_MEM_WRITE; + sect->flags = COFF_SectionFlag_CntInitializedData|(COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift)|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite; } { @@ -874,7 +874,7 @@ lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_MachineType m symbol->name.long_name.zeroes = 0; symbol->name.long_name.string_table_offset = symbol_name_off; symbol->section_number = 1; - symbol->storage_class = COFF_SymStorageClass_EXTERNAL; + symbol->storage_class = COFF_SymStorageClass_External; } // update string table size @@ -908,7 +908,7 @@ lnk_build_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stam str8_list_pushf(scratch.arena, &list, "`\n"); String8 result = str8_list_join(arena, &list, 0); - Assert(result.size == COFF_ARCHIVE_MEMBER_HEADER_SIZE); + Assert(result.size == sizeof(COFF_ArchiveMemberHeader)); scratch_end(scratch); ProfEnd(); return result; diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index d971b459..d53802d2 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -327,7 +327,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) String8 cached_lib_path = push_str8_copy(arena, input->lib_path); // parse coff obj - COFF_HeaderInfo coff_info = coff_header_info_from_data(input->data); + COFF_FileHeaderInfo coff_info = coff_file_header_info_from_data(input->data); Rng1U64 coff_file_header_range = rng_1u64(0, coff_info.header_size); Rng1U64 coff_sect_arr_range = rng_1u64(coff_info.section_array_off, coff_info.section_array_off + coff_info.section_count_no_null * sizeof(COFF_SectionHeader)); Rng1U64 coff_symbols_range = rng_1u64(coff_info.symbol_off, coff_info.symbol_off + coff_info.symbol_count * coff_info.symbol_size); @@ -368,13 +368,13 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) COFF_SectionHeader *coff_sect = &coff_sect_arr[sect_idx]; // read name - String8 sect_name = coff_name_from_section_header(coff_sect, input->data, coff_info.string_table_off); + String8 sect_name = coff_name_from_section_header(input->data, coff_sect, coff_info.string_table_off); // parse section name coff_parse_section_name(sect_name, §_name_arr[sect_idx], §_sort_arr[sect_idx]); String8 data; - if (coff_sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (coff_sect->flags & COFF_SectionFlag_CntUninitializedData) { data = str8(0, coff_sect->fsize); } else { if (coff_sect->fsize > 0) { @@ -403,7 +403,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) LNK_Chunk *chunk = &chunk_arr[sect_idx]; chunk->align = coff_align_size_from_section_flags(coff_sect->flags); - chunk->is_discarded = !!(coff_sect->flags & COFF_SectionFlag_LNK_REMOVE); + chunk->is_discarded = !!(coff_sect->flags & COFF_SectionFlag_LnkRemove); chunk->sort_chunk = 1; chunk->type = LNK_Chunk_Leaf; chunk->sort_idx = sect_sort_arr[sect_idx]; @@ -433,8 +433,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) } // convert from coff - B32 is_big_obj = coff_info.type == COFF_DataType_BIG_OBJ; - LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, cached_lib_path, is_big_obj, function_pad_min, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_info.symbol_count, coff_symbols, chunk_ptr_arr, master_common_block); + LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, cached_lib_path, coff_info.is_big_obj, function_pad_min, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_info.symbol_count, coff_symbols, chunk_ptr_arr, master_common_block); LNK_SymbolList symbol_list = lnk_symbol_list_from_array(arena, symbol_arr); LNK_RelocList *reloc_list_arr = lnk_reloc_list_array_from_coff(arena, coff_info.machine, input->data, coff_info.section_count_no_null, coff_sect_arr, chunk_ptr_arr, symbol_arr); LNK_DirectiveInfo directive_info = lnk_directive_info_from_sections(arena, cached_path, cached_lib_path, coff_info.section_count_no_null, reloc_list_arr, sect_name_arr, chunk_arr); @@ -495,7 +494,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_new_sect_scanner) for (U64 chunk_idx = 0; chunk_idx < obj->chunk_count; chunk_idx += 1) { String8 sect_name = obj->sect_name_arr[chunk_idx]; - COFF_SectionFlags sect_flags = obj->chunk_arr[chunk_idx]->flags & ~COFF_SectionFlags_LNK_FLAGS; + COFF_SectionFlags sect_flags = obj->chunk_arr[chunk_idx]->flags & ~COFF_SectionFlags_LnkFlags; KeyValuePair *is_present = hash_table_search_string(ht, sect_name); if (is_present) { @@ -675,7 +674,7 @@ lnk_obj_list_push_parallel(TP_Context *tp, // push new sections for :find_chunk_section for (LNK_SectDefn *curr = new_list.first; curr != 0; curr = curr->next) { - lnk_section_table_push(st, curr->name, curr->flags & ~COFF_SectionFlags_LNK_FLAGS); + lnk_section_table_push(st, curr->name, curr->flags & ~COFF_SectionFlags_LnkFlags); } tp_temp_end(temp); @@ -763,7 +762,7 @@ lnk_symbol_array_from_coff(Arena *arena, // is this a function symbol? COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); - if (interp == COFF_SymbolValueInterp_REGULAR && COFF_SymbolType_IsFunc(symbol.type)) { + if (interp == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) { if (symbol.section_number == 0 || symbol.section_number > sect_count) { lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "out ouf bounds section index in symbol \"%S (%u)\"", symbol.name, symbol.section_number); } @@ -879,7 +878,7 @@ lnk_symbol_array_from_coff(Arena *arena, COFF_SymbolValueInterpType interp = coff_interp_symbol(parsed_symbol.section_number, parsed_symbol.value, parsed_symbol.storage_class); switch (interp) { - case COFF_SymbolValueInterp_REGULAR: { + case COFF_SymbolValueInterp_Regular: { if (parsed_symbol.section_number == 0 || parsed_symbol.section_number > sect_count) { lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "symbol %S (No. %llx) has out ouf bounds section index %x", parsed_symbol.name, symbol_idx, parsed_symbol.section_number); } @@ -889,7 +888,7 @@ lnk_symbol_array_from_coff(Arena *arena, LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static; - if (parsed_symbol.storage_class == COFF_SymStorageClass_EXTERNAL) { + if (parsed_symbol.storage_class == COFF_SymStorageClass_External) { visibility = LNK_DefinedSymbolVisibility_Extern; } LNK_DefinedSymbolFlags flags = 0; @@ -900,15 +899,15 @@ lnk_symbol_array_from_coff(Arena *arena, LNK_Chunk *chunk = chunk_ptr_arr[parsed_symbol.section_number-1]; U64 offset = parsed_symbol.value; - COFF_ComdatSelectType selection = COFF_ComdatSelectType_ANY; + COFF_ComdatSelectType selection = COFF_ComdatSelect_Any; U64 check_sum = 0; - B32 is_comdat = (coff_sect_arr[parsed_symbol.section_number-1].flags & COFF_SectionFlag_LNK_COMDAT) && + B32 is_comdat = (coff_sect_arr[parsed_symbol.section_number-1].flags & COFF_SectionFlag_LnkCOMDAT) && parsed_symbol.value == 0 && parsed_symbol.aux_symbol_count > 0 && - parsed_symbol.type.u.lsb == COFF_SymType_NULL && - parsed_symbol.storage_class == COFF_SymStorageClass_STATIC; + parsed_symbol.type.u.lsb == COFF_SymType_Null && + parsed_symbol.storage_class == COFF_SymStorageClass_Static; if (is_comdat) { COFF_SymbolSecDef *secdef = aux_symbols; @@ -916,7 +915,7 @@ lnk_symbol_array_from_coff(Arena *arena, check_sum = secdef->check_sum; // create association link between chunks - if (secdef->selection == COFF_ComdatSelectType_ASSOCIATIVE) { + if (secdef->selection == COFF_ComdatSelect_Associative) { U32 secdef_number = secdef->number_lo; // promote secdef number to 32 bits @@ -955,7 +954,7 @@ lnk_symbol_array_from_coff(Arena *arena, lnk_init_defined_symbol_chunk(&symbol_array.v[symbol_idx], parsed_symbol.name, visibility, flags, chunk, offset, selection, check_sum); symbol_array.v[symbol_idx].obj = obj; } break; - case COFF_SymbolValueInterp_WEAK: { + case COFF_SymbolValueInterp_Weak: { if (parsed_symbol.aux_symbol_count == 0) { lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "weak symbol \"%S (%u)\" must at least one aux symbol", parsed_symbol.name, symbol_idx); } @@ -972,12 +971,12 @@ lnk_symbol_array_from_coff(Arena *arena, symbol->obj = obj; fallback_symbol->obj = obj; } break; - case COFF_SymbolValueInterp_UNDEFINED: { + case COFF_SymbolValueInterp_Undefined: { LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; lnk_init_undefined_symbol(symbol, parsed_symbol.name, LNK_SymbolScopeFlag_Main); symbol->obj = obj; } break; - case COFF_SymbolValueInterp_COMMON: { + case COFF_SymbolValueInterp_Common: { // :common_block // // TODO: sort chunks on size to reduce bss usage @@ -995,16 +994,16 @@ lnk_symbol_array_from_coff(Arena *arena, } LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; - lnk_init_defined_symbol_chunk(symbol, parsed_symbol.name, LNK_DefinedSymbolVisibility_Extern, flags, chunk, 0, COFF_ComdatSelectType_LARGEST, 0); + lnk_init_defined_symbol_chunk(symbol, parsed_symbol.name, LNK_DefinedSymbolVisibility_Extern, flags, chunk, 0, COFF_ComdatSelect_Largest, 0); symbol->obj = obj; } break; - case COFF_SymbolValueInterp_ABS: { + case COFF_SymbolValueInterp_Abs: { // Never code or data, synthetic symbol. COFF spec says bits in value are used // as flags in symbol @feat.00, other symbols like @comp.id and @vol.md are undocumented. // LLVM uses undocumented mask 0x4800 on @feat.00 to tell if object was compiled with /guard:cf. LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static; - if (parsed_symbol.storage_class == COFF_SymStorageClass_EXTERNAL) { + if (parsed_symbol.storage_class == COFF_SymStorageClass_External) { visibility = LNK_DefinedSymbolVisibility_Extern; } @@ -1012,7 +1011,7 @@ lnk_symbol_array_from_coff(Arena *arena, lnk_init_defined_symbol_va(symbol, parsed_symbol.name, visibility, 0, parsed_symbol.value); symbol->obj = obj; } break; - case COFF_SymbolValueInterp_DEBUG: { + case COFF_SymbolValueInterp_Debug: { } break; } } @@ -1025,8 +1024,8 @@ lnk_reloc_list_array_from_coff(Arena *arena, COFF_MachineType machine, String8 c { LNK_RelocList *reloc_list_arr = push_array_no_zero(arena, LNK_RelocList, sect_count); for (U64 sect_idx = 0; sect_idx < sect_count; ++sect_idx) { - COFF_SectionHeader *coff_header = &coff_sect_arr[sect_idx]; - COFF_RelocInfo coff_reloc_info = coff_reloc_info_from_section_header(coff_data, coff_header); + COFF_SectionHeader *COFF_FileHeader = &coff_sect_arr[sect_idx]; + COFF_RelocInfo coff_reloc_info = coff_reloc_info_from_section_header(coff_data, COFF_FileHeader); COFF_Reloc *coff_reloc_v = (COFF_Reloc *)(coff_data.str + coff_reloc_info.array_off); LNK_Chunk *sect_chunk = chunk_ptr_arr[sect_idx]; reloc_list_arr[sect_idx] = lnk_reloc_list_from_coff_reloc_array(arena, machine, sect_chunk, symbol_array, coff_reloc_v, coff_reloc_info.count); @@ -1122,8 +1121,8 @@ lnk_directive_info_from_sections(Arena *arena, if (str8_match_lit(".drectve", sect_name, 0)) { if (sect_chunk->type == LNK_Chunk_Leaf) { if (sect_chunk->u.leaf.size >= 3) { - if (~sect_chunk->flags & COFF_SectionFlag_LNK_INFO) { - lnk_error_with_loc(LNK_Warning_IllData, obj_path, lib_path, "%S missing COFF_SectionFlag_LNK_INFO", sect_name); + if (~sect_chunk->flags & COFF_SectionFlag_LnkInfo) { + lnk_error_with_loc(LNK_Warning_IllData, obj_path, lib_path, "%S missing COFF_SectionFlag_LnkInfo", sect_name); } if (reloc_list_arr[chunk_idx].count > 0) { lnk_error_with_loc(LNK_Warning_DirectiveSectionWithRelocs, obj_path, lib_path, "directive section %S(%#x) has relocations", sect_name, (chunk_idx+1)); diff --git a/src/linker/lnk_reloc.c b/src/linker/lnk_reloc.c index 0c52820d..b37120bd 100644 --- a/src/linker/lnk_reloc.c +++ b/src/linker/lnk_reloc.c @@ -117,26 +117,26 @@ lnk_ext_reloc_type_from_coff(COFF_MachineType machine, U32 type) { LNK_RelocType result = LNK_Reloc_NULL; switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X64: { + case COFF_Machine_Unknown: break; + case COFF_Machine_X64: { switch (type) { - case COFF_RelocTypeX64_ABS: result = LNK_Reloc_NULL; break; - case COFF_RelocTypeX64_ADDR64: result = LNK_Reloc_ADDR_64; break; - case COFF_RelocTypeX64_ADDR32: result = LNK_Reloc_ADDR_32; break; - case COFF_RelocTypeX64_ADDR32NB: result = LNK_Reloc_VIRT_OFF_32; break; - case COFF_RelocTypeX64_REL32: result = LNK_Reloc_REL32; break; - case COFF_RelocTypeX64_REL32_1: result = LNK_Reloc_REL32_1; break; - case COFF_RelocTypeX64_REL32_2: result = LNK_Reloc_REL32_2; break; - case COFF_RelocTypeX64_REL32_3: result = LNK_Reloc_REL32_3; break; - case COFF_RelocTypeX64_REL32_4: result = LNK_Reloc_REL32_4; break; - case COFF_RelocTypeX64_REL32_5: result = LNK_Reloc_REL32_5; break; - case COFF_RelocTypeX64_SECTION: result = LNK_Reloc_SECT_IDX; break; - case COFF_RelocTypeX64_SECREL: result = LNK_Reloc_SECT_REL; break; - case COFF_RelocTypeX64_SECREL7: lnk_not_implemented("TODO: COFF_RelocTypeX64_SECREL7"); break; - case COFF_RelocTypeX64_TOKEN: lnk_not_implemented("TODO: COFF_RelocTypeX64_TOKEN"); break; - case COFF_RelocTypeX64_SREL32: lnk_not_implemented("TODO: COFF_RelocTypeX64_SREL32"); break; - case COFF_RelocTypeX64_PAIR: lnk_not_implemented("TODO: COFF_RelocTypeX64_PAIR"); break; - case COFF_RelocTypeX64_SSPAN32: lnk_not_implemented("TODO: COFF_RelocTypeX64_SSPAN32"); break; + case COFF_Reloc_X64_Abs: result = LNK_Reloc_NULL; break; + case COFF_Reloc_X64_Addr64: result = LNK_Reloc_ADDR_64; break; + case COFF_Reloc_X64_Addr32: result = LNK_Reloc_ADDR_32; break; + case COFF_Reloc_X64_Addr32Nb: result = LNK_Reloc_VIRT_OFF_32; break; + case COFF_Reloc_X64_Rel32: result = LNK_Reloc_REL32; break; + case COFF_Reloc_X64_Rel32_1: result = LNK_Reloc_REL32_1; break; + case COFF_Reloc_X64_Rel32_2: result = LNK_Reloc_REL32_2; break; + case COFF_Reloc_X64_Rel32_3: result = LNK_Reloc_REL32_3; break; + case COFF_Reloc_X64_Rel32_4: result = LNK_Reloc_REL32_4; break; + case COFF_Reloc_X64_Rel32_5: result = LNK_Reloc_REL32_5; break; + case COFF_Reloc_X64_Section: result = LNK_Reloc_SECT_IDX; break; + case COFF_Reloc_X64_SecRel: result = LNK_Reloc_SECT_REL; break; + case COFF_Reloc_X64_SecRel7: lnk_not_implemented("TODO: COFF_Reloc_X64_SecRel7"); break; + case COFF_Reloc_X64_Token: lnk_not_implemented("TODO: COFF_Reloc_X64_Token"); break; + case COFF_Reloc_X64_SRel32: lnk_not_implemented("TODO: COFF_Reloc_X64_SRel32"); break; + case COFF_Reloc_X64_Pair: lnk_not_implemented("TODO: COFF_Reloc_X64_Pair"); break; + case COFF_Reloc_X64_SSpan32: lnk_not_implemented("TODO: COFF_Reloc_X64_SSpan32"); break; default: lnk_invalid_path("unknown relocation type 0x%X", type); } } break; @@ -150,20 +150,20 @@ lnk_ext_reloc_type_to_coff(COFF_MachineType machine, LNK_RelocType type) { U32 result = 0; switch (machine) { - case COFF_MachineType_X64: { + case COFF_Machine_X64: { switch (type) { - case LNK_Reloc_NULL: result = COFF_RelocTypeX64_ABS; break; - case LNK_Reloc_ADDR_64: result = COFF_RelocTypeX64_ADDR64; break; - case LNK_Reloc_ADDR_32: result = COFF_RelocTypeX64_ADDR32; break; - case LNK_Reloc_VIRT_OFF_32: result = COFF_RelocTypeX64_ADDR32NB; break; - case LNK_Reloc_REL32: result = COFF_RelocTypeX64_REL32; break; - case LNK_Reloc_REL32_1: result = COFF_RelocTypeX64_REL32_1; break; - case LNK_Reloc_REL32_2: result = COFF_RelocTypeX64_REL32_2; break; - case LNK_Reloc_REL32_3: result = COFF_RelocTypeX64_REL32_3; break; - case LNK_Reloc_REL32_4: result = COFF_RelocTypeX64_REL32_4; break; - case LNK_Reloc_REL32_5: result = COFF_RelocTypeX64_REL32_5; break; - case LNK_Reloc_SECT_IDX: result = COFF_RelocTypeX64_SECTION; break; - case LNK_Reloc_SECT_REL: result = COFF_RelocTypeX64_SECREL; break; + case LNK_Reloc_NULL: result = COFF_Reloc_X64_Abs; break; + case LNK_Reloc_ADDR_64: result = COFF_Reloc_X64_Addr64; break; + case LNK_Reloc_ADDR_32: result = COFF_Reloc_X64_Addr32; break; + case LNK_Reloc_VIRT_OFF_32: result = COFF_Reloc_X64_Addr32Nb; break; + case LNK_Reloc_REL32: result = COFF_Reloc_X64_Rel32; break; + case LNK_Reloc_REL32_1: result = COFF_Reloc_X64_Rel32_1; break; + case LNK_Reloc_REL32_2: result = COFF_Reloc_X64_Rel32_2; break; + case LNK_Reloc_REL32_3: result = COFF_Reloc_X64_Rel32_3; break; + case LNK_Reloc_REL32_4: result = COFF_Reloc_X64_Rel32_4; break; + case LNK_Reloc_REL32_5: result = COFF_Reloc_X64_Rel32_5; break; + case LNK_Reloc_SECT_IDX: result = COFF_Reloc_X64_Section; break; + case LNK_Reloc_SECT_REL: result = COFF_Reloc_X64_SecRel; break; default: InvalidPath; } } break; diff --git a/src/linker/lnk_section_table.c b/src/linker/lnk_section_table.c index b3d135ac..4ac8cb25 100644 --- a/src/linker/lnk_section_table.c +++ b/src/linker/lnk_section_table.c @@ -85,7 +85,7 @@ lnk_make_section_sort_index(Arena *arena, String8 name, COFF_SectionFlags flags, // pack sections with run-time data closer String8List sort_index_list = {0}; - if (flags & COFF_SectionFlag_MEM_DISCARDABLE) { + if (flags & COFF_SectionFlag_MemDiscardable) { str8_list_pushf(scratch.arena, &sort_index_list, "b"); } else { str8_list_pushf(scratch.arena, &sort_index_list, "a"); @@ -102,14 +102,14 @@ lnk_make_section_sort_index(Arena *arena, String8 name, COFF_SectionFlags flags, } // sort sections based on the contents - if (flags & COFF_SectionFlag_CNT_CODE) { + if (flags & COFF_SectionFlag_CntCode) { str8_list_pushf(scratch.arena, &sort_index_list, "a"); if (str8_match_lit(".text", name, 0)) { str8_list_pushf(scratch.arena, &sort_index_list, "a"); } else { str8_list_pushf(scratch.arena, &sort_index_list, "b"); } - } else if (flags & COFF_SectionFlag_CNT_INITIALIZED_DATA) { + } else if (flags & COFF_SectionFlag_CntInitializedData) { str8_list_pushf(scratch.arena, &sort_index_list, "b"); if (str8_match_lit(".data", name, 0)) { str8_list_pushf(scratch.arena, &sort_index_list, "a"); @@ -120,14 +120,14 @@ lnk_make_section_sort_index(Arena *arena, String8 name, COFF_SectionFlags flags, } else { str8_list_pushf(scratch.arena, &sort_index_list, "d"); } - } else if (flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + } else if (flags & COFF_SectionFlag_CntUninitializedData) { str8_list_pushf(scratch.arena, &sort_index_list, "c"); } else { str8_list_pushf(scratch.arena, &sort_index_list, "d"); } // sort sections based on read/write access so final section layout looks cleaner - if (flags & COFF_SectionFlag_MEM_READ && ~flags & COFF_SectionFlag_MEM_WRITE) { + if (flags & COFF_SectionFlag_MemRead && ~flags & COFF_SectionFlag_MemWrite) { str8_list_pushf(scratch.arena, &sort_index_list, "a"); } else { str8_list_pushf(scratch.arena, &sort_index_list, "b"); @@ -236,8 +236,8 @@ lnk_code_align_byte_from_machine(COFF_MachineType machine) { U8 align_byte = 0; switch (machine) { - case COFF_MachineType_X64: - case COFF_MachineType_X86: { + case COFF_Machine_X64: + case COFF_Machine_X86: { align_byte = 0xCC; } break; default: { @@ -570,7 +570,7 @@ lnk_section_table_assign_file_offsets(LNK_SectionTable *st) U64 cursor = 0; for (LNK_SectionNode *sect_node = st->list.first; sect_node != NULL; sect_node = sect_node->next) { LNK_Section *sect = §_node->data; - if (sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (sect->flags & COFF_SectionFlag_CntUninitializedData) { continue; } if (!sect->has_layout) continue; @@ -617,7 +617,7 @@ lnk_section_table_serialize(TP_Context *tp, Arena *arena, LNK_SectionTable *st, for (LNK_SectionNode *sect_n = st->list.first; sect_n != 0; sect_n = sect_n->next) { LNK_Section *sect = §_n->data; if (sect->has_layout) { - if (sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (sect->flags & COFF_SectionFlag_CntUninitializedData) { continue; } @@ -625,7 +625,7 @@ lnk_section_table_serialize(TP_Context *tp, Arena *arena, LNK_SectionTable *st, String8 sect_data = str8_substr(image, rng_1u64(image_cursor, image_cursor + sect_size)); U8 fill_byte = 0; - if (sect->flags & COFF_SectionFlag_CNT_CODE) { + if (sect->flags & COFF_SectionFlag_CntCode) { fill_byte = lnk_code_align_byte_from_machine(machine); } diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index 3332aa1b..127a6f1d 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -271,17 +271,17 @@ lnk_can_replace_symbol(const LNK_Symbol *dst, const LNK_Symbol *src) COFF_ComdatSelectType src_select = src_defn->u.selection; // handle objs compiled with /GR- and /GR - if ((src_select == COFF_ComdatSelectType_ANY && dst_select == COFF_ComdatSelectType_LARGEST) || - (src_select == COFF_ComdatSelectType_LARGEST && dst_select == COFF_ComdatSelectType_ANY)) { - dst_select = COFF_ComdatSelectType_LARGEST; - src_select = COFF_ComdatSelectType_LARGEST; + if ((src_select == COFF_ComdatSelect_Any && dst_select == COFF_ComdatSelect_Largest) || + (src_select == COFF_ComdatSelect_Largest && dst_select == COFF_ComdatSelect_Any)) { + dst_select = COFF_ComdatSelect_Largest; + src_select = COFF_ComdatSelect_Largest; } if (src_select == dst_select) { switch (src_select) { default: InvalidPath; - case COFF_ComdatSelectType_NULL: - case COFF_ComdatSelectType_ANY: { + case COFF_ComdatSelect_Null: + case COFF_ComdatSelect_Any: { LNK_Chunk *dst_chunk = dst_defn->u.chunk; LNK_Chunk *src_chunk = src_defn->u.chunk; U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); @@ -293,10 +293,10 @@ lnk_can_replace_symbol(const LNK_Symbol *dst, const LNK_Symbol *src) can_replace = src_chunk_size < dst_chunk_size; } } break; - case COFF_ComdatSelectType_NODUPLICATES: { + case COFF_ComdatSelect_NoDuplicates: { lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); } break; - case COFF_ComdatSelectType_SAME_SIZE: { + case COFF_ComdatSelect_SameSize: { LNK_Chunk *dst_chunk = dst_defn->u.chunk; LNK_Chunk *src_chunk = src_defn->u.chunk; U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); @@ -306,13 +306,13 @@ lnk_can_replace_symbol(const LNK_Symbol *dst, const LNK_Symbol *src) lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); } } break; - case COFF_ComdatSelectType_EXACT_MATCH: { + case COFF_ComdatSelect_ExactMatch: { B32 is_exact_match = (dst_defn->u.check_sum == src_defn->u.check_sum); if (!is_exact_match) { lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); } } break; - case COFF_ComdatSelectType_LARGEST: { + case COFF_ComdatSelect_Largest: { LNK_Chunk *dst_chunk = dst_defn->u.chunk; LNK_Chunk *src_chunk = src_defn->u.chunk; U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); @@ -330,7 +330,7 @@ lnk_can_replace_symbol(const LNK_Symbol *dst, const LNK_Symbol *src) can_replace = dst_chunk_size < src_chunk_size; } } break; - case COFF_ComdatSelectType_ASSOCIATIVE: { + case COFF_ComdatSelect_Associative: { // ignore } break; } @@ -630,7 +630,7 @@ lnk_symbol_table_push_weak(LNK_SymbolTable *symtab, String8 weak_name, COFF_Weak weak_name = push_str8_copy(symtab->arena->v[0], weak_name); strong_name = push_str8_copy(symtab->arena->v[0], strong_name); LNK_Symbol *strong_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], strong_name, LNK_SymbolScopeFlag_Main); - LNK_Symbol *weak_symbol = lnk_make_weak_symbol(symtab->arena->v[0], weak_name, COFF_WeakExtType_SEARCH_ALIAS, strong_symbol); + LNK_Symbol *weak_symbol = lnk_make_weak_symbol(symtab->arena->v[0], weak_name, COFF_WeakExt_SearchAlias, strong_symbol); lnk_symbol_table_push(symtab, weak_symbol); return weak_symbol; } diff --git a/src/linker/pdb_ext/pdb_builder.c b/src/linker/pdb_ext/pdb_builder.c index 2fbf706b..ffabb1c6 100644 --- a/src/linker/pdb_ext/pdb_builder.c +++ b/src/linker/pdb_ext/pdb_builder.c @@ -3270,21 +3270,21 @@ dbi_build_sec_map(Arena *arena, PDB_DbiContext *dbi) U64 isect = 0; for (PDB_DbiSectionNode *sect = dbi->section_list.first; sect; sect = sect->next, ++isect) { PDB_DbiSecMapEntry *s = &entry_array[isect]; - COFF_SectionHeader *coff_header = §->data; - if (coff_header->flags & COFF_SectionFlag_MEM_READ) { + COFF_SectionHeader *section_header = §->data; + if (section_header->flags & COFF_SectionFlag_MemRead) { s->flags |= PDB_DbiOMF_READ; } - if (coff_header->flags & COFF_SectionFlag_MEM_WRITE) { + if (section_header->flags & COFF_SectionFlag_MemWrite) { s->flags |= PDB_DbiOMF_WRITE; } - if (coff_header->flags & COFF_SectionFlag_MEM_EXECUTE) { + if (section_header->flags & COFF_SectionFlag_MemExecute) { s->flags |= PDB_DbiOMF_EXEC; } - if (~coff_header->flags & COFF_SectionFlag_MEM_16BIT) { + if (~section_header->flags & COFF_SectionFlag_Mem16Bit) { s->flags |= PDB_DbiOMF_IS_32BIT_ADDR; } s->flags |= PDB_DbiOMF_IS_SELECTOR; // always set - s->sec_size = coff_header->vsize; + s->sec_size = section_header->vsize; s->frame = isect + 1; s->sec_name = max_U16; s->class_name = max_U16; @@ -3444,7 +3444,7 @@ dbi_module_push_section_contrib(PDB_DbiContext *dbi, // Mod1::fUpdateSecContrib if (mod->first_sc.base.mod == 0) { - if (flags & COFF_SectionFlag_CNT_CODE) { + if (flags & COFF_SectionFlag_CntCode) { mod->first_sc = sc; } } diff --git a/src/linker/rdi/rdi_coff.c b/src/linker/rdi/rdi_coff.c index 07a3892f..32b93862 100644 --- a/src/linker/rdi/rdi_coff.c +++ b/src/linker/rdi/rdi_coff.c @@ -5,31 +5,31 @@ internal RDI_Arch rdi_arch_from_coff_machine(COFF_MachineType machine) { switch (machine) { - case COFF_MachineType_X86: return RDI_Arch_X86; - case COFF_MachineType_X64: return RDI_Arch_X64; + case COFF_Machine_X86: return RDI_Arch_X86; + case COFF_Machine_X64: return RDI_Arch_X64; - case COFF_MachineType_UNKNOWN: - case COFF_MachineType_AM33: - case COFF_MachineType_ARM: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARMNT: - case COFF_MachineType_EBC: - case COFF_MachineType_IA64: - case COFF_MachineType_M32R: - case COFF_MachineType_MIPS16: - case COFF_MachineType_MIPSFPU: - case COFF_MachineType_MIPSFPU16: - case COFF_MachineType_POWERPC: - case COFF_MachineType_POWERPCFP: - case COFF_MachineType_R4000: - case COFF_MachineType_RISCV32: - case COFF_MachineType_RISCV64: - case COFF_MachineType_SH3: - case COFF_MachineType_SH3DSP: - case COFF_MachineType_SH4: - case COFF_MachineType_SH5: - case COFF_MachineType_THUMB: - case COFF_MachineType_WCEMIPSV2: + case COFF_Machine_Unknown: + case COFF_Machine_Am33: + case COFF_Machine_Arm: + case COFF_Machine_Arm64: + case COFF_Machine_ArmNt: + case COFF_Machine_Ebc: + case COFF_Machine_Ia64: + case COFF_Machine_M32R: + case COFF_Machine_Mips16: + case COFF_Machine_MipsFpu: + case COFF_Machine_MipsFpu16: + case COFF_Machine_PowerPc: + case COFF_Machine_PowerPcFp: + case COFF_Machine_R4000: + case COFF_Machine_RiscV32: + case COFF_Machine_RiscV64: + case COFF_Machine_Sh3: + case COFF_Machine_Sh3Dsp: + case COFF_Machine_Sh4: + case COFF_Machine_Sh5: + case COFF_Machine_Thumb: + case COFF_Machine_WceMipsV2: NotImplemented; default: return RDI_Arch_NULL; @@ -40,13 +40,13 @@ internal RDI_BinarySectionFlags rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) { RDI_BinarySectionFlags result = 0; - if (flags & COFF_SectionFlag_MEM_READ) { + if (flags & COFF_SectionFlag_MemRead) { result |= RDI_BinarySectionFlag_Read; } - if (flags & COFF_SectionFlag_MEM_WRITE) { + if (flags & COFF_SectionFlag_MemWrite) { result |= RDI_BinarySectionFlag_Write; } - if (flags & COFF_SectionFlag_MEM_EXECUTE) { + if (flags & COFF_SectionFlag_MemExecute) { result |= RDI_BinarySectionFlag_Execute; } return result; diff --git a/src/pe/pe.c b/src/pe/pe.c index 352e775e..a4bac235 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -438,34 +438,34 @@ pe_bin_info_from_data(Arena *arena, String8 data) } // rjf: read coff header - U32 coff_header_off = dos_header.coff_file_offset + sizeof(pe_magic); - COFF_Header coff_header = {0}; + U32 file_header_off = dos_header.coff_file_offset + sizeof(pe_magic); + COFF_FileHeader file_header = {0}; if(valid) { - str8_deserial_read_struct(data, coff_header_off, &coff_header); + str8_deserial_read_struct(data, file_header_off, &file_header); } // rjf: range of optional extension header ("optional" for short) - U32 optional_size = coff_header.optional_header_size; - U64 after_coff_header_off = coff_header_off + sizeof(coff_header); - U64 after_optional_header_off = after_coff_header_off + optional_size; + U32 optional_size = file_header.optional_header_size; + U64 after_file_header_off = file_header_off + sizeof(COFF_FileHeader); + U64 after_optional_header_off = after_file_header_off + optional_size; Rng1U64 optional_range = {0}; if(valid) { - optional_range.min = ClampTop(after_coff_header_off, data.size); + optional_range.min = ClampTop(after_file_header_off, data.size); optional_range.max = ClampTop(after_optional_header_off, data.size); } // rjf: get sections U64 sec_array_off = optional_range.max; - U64 sec_array_raw_opl = sec_array_off + coff_header.section_count*sizeof(COFF_SectionHeader); + U64 sec_array_raw_opl = sec_array_off + file_header.section_count*sizeof(COFF_SectionHeader); U64 sec_array_opl = ClampTop(sec_array_raw_opl, data.size); U64 clamped_sec_count = (sec_array_opl - sec_array_off)/sizeof(COFF_SectionHeader); COFF_SectionHeader *sections = (COFF_SectionHeader*)(data.str + sec_array_off); // rjf: get symbols - U64 symbol_array_off = coff_header.symbol_table_foff; - U64 symbol_count = coff_header.symbol_count; + U64 symbol_array_off = file_header.symbol_table_foff; + U64 symbol_count = file_header.symbol_count; // rjf: get string table U64 string_table_off = symbol_array_off + sizeof(COFF_Symbol16) * symbol_count; @@ -551,11 +551,11 @@ pe_bin_info_from_data(Arena *arena, String8 data) if(valid && PE_DataDirectoryIndex_TLS < data_dir_count) { Rng1U64 tls_header_frng = data_dir_franges[PE_DataDirectoryIndex_TLS]; - switch(coff_header.machine) + switch(file_header.machine) { default:{ NotImplemented; }break; - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: { PE_TLSHeader32 tls_header32 = {0}; if(str8_deserial_read_struct(data, tls_header_frng.min, &tls_header32) == sizeof(tls_header32)) @@ -572,7 +572,7 @@ pe_bin_info_from_data(Arena *arena, String8 data) Assert(!"unable to read TLS Header 32"); } }break; - case COFF_MachineType_X64: + case COFF_Machine_X64: { if(str8_deserial_read_struct(data, tls_header_frng.min, &tls_header) != sizeof(tls_header)) { @@ -598,7 +598,7 @@ pe_bin_info_from_data(Arena *arena, String8 data) info.string_table_off = string_table_off; info.data_dir_franges = data_dir_franges; info.data_dir_count = data_dir_count; - info.arch = arch_from_coff_machine(coff_header.machine); + info.arch = arch_from_coff_machine(file_header.machine); info.tls_header = tls_header; } @@ -824,7 +824,7 @@ pe_foff_from_voff(String8 data, PE_BinInfo *bin, U64 voff) COFF_SectionHeader *sect = §ions[sect_idx]; if(sect->voff <= voff && voff < sect->voff + sect->vsize) { - if(!(sect->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA)) + if(!(sect->flags & COFF_SectionFlag_CntUninitializedData)) { foff = sect->foff + (voff - sect->voff); } @@ -967,7 +967,7 @@ pe_get_entry_point_names(COFF_MachineType machine, String8Array entry_point_names = {0}; if (file_characteristics & PE_ImageFileCharacteristic_FILE_DLL) { - if (machine == COFF_MachineType_X86) { + if (machine == COFF_Machine_X86) { read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("__DllMainCRTStartup@12"), }; @@ -1418,8 +1418,8 @@ pe_tls_from_data(Arena *arena, U64 *callback_addrs = 0; switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: { + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: { PE_TLSHeader32 header32 = {0}; str8_deserial_read_struct(raw_tls, 0, &header32); @@ -1444,7 +1444,7 @@ pe_tls_from_data(Arena *arena, callback_addrs[i] = (U64)src[i]; } } break; - case COFF_MachineType_X64: { + case COFF_Machine_X64: { str8_deserial_read_struct(raw_tls, 0, &header64); U64 callbacks_voff = header64.callbacks_address - image_base; @@ -1487,9 +1487,9 @@ pe_resource_dir_push_dir_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID PE_ResourceList *list = 0; switch (id.type) { default: - case COFF_ResourceIDType_NULL: break; - case COFF_ResourceIDType_STRING: list = &dir->named_list; break; - case COFF_ResourceIDType_NUMBER: list = &dir->id_list; break; + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_String: list = &dir->named_list; break; + case COFF_ResourceIDType_Number: list = &dir->id_list; break; } PE_ResourceNode *res_node = push_array(arena, PE_ResourceNode, 1); @@ -1516,9 +1516,9 @@ pe_resource_dir_push_entry_node(Arena *arena, PE_ResourceDir *dir, COFF_Resource PE_ResourceList *list = NULL; switch (id.type) { default: - case COFF_ResourceIDType_NULL: break; - case COFF_ResourceIDType_STRING: list = &dir->named_list; break; - case COFF_ResourceIDType_NUMBER: list = &dir->id_list; break; + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_String: list = &dir->named_list; break; + case COFF_ResourceIDType_Number: list = &dir->id_list; break; } PE_ResourceNode *res_node = push_array(arena, PE_ResourceNode, 1); @@ -1555,7 +1555,7 @@ internal PE_ResourceNode * pe_resource_dir_search_node(PE_ResourceDir *dir, COFF_ResourceID id) { for (PE_ResourceNode *i = dir->id_list.first; i != NULL; i = i->next) { - if (coff_resource_id_is_equal(i->data.id, id)) { + if (coff_resource_id_compar(&i->data.id, &id)) { return i; } } @@ -1586,11 +1586,11 @@ pe_resource_dir_push_res_file(Arena *arena, PE_ResourceDir *root_dir, String8 re { // parse file into resource list String8 res_data = str8_substr(res_file, rng_1u64(sizeof(PE_RES_MAGIC), res_file.size)); - COFF_ResourceList list = coff_resource_list_from_data(arena, res_data); + COFF_ParsedResourceList list = coff_resource_list_from_data(arena, res_data); // move resources to directories based on type - for (COFF_ResourceNode *res_node = list.first; res_node != NULL; res_node = res_node->next) { - COFF_Resource *res = &res_node->data; + for (COFF_ParsedResourceNode *res_node = list.first; res_node != NULL; res_node = res_node->next) { + COFF_ParsedResource *res = &res_node->data; // search existing directories PE_Resource *dir_res = pe_resource_dir_search(root_dir, res->type); @@ -1612,7 +1612,7 @@ pe_resource_dir_push_res_file(Arena *arena, PE_ResourceDir *root_dir, String8 re // push entry PE_Resource *sub_dir_res = pe_resource_dir_push_dir(arena, dir, res->name, 0, 0, 0, 0); COFF_ResourceID id; - id.type = COFF_ResourceIDType_NUMBER; + id.type = COFF_ResourceIDType_Number; id.u.number = res->language_id; pe_resource_dir_push_entry(arena, sub_dir_res->u.dir, id, res->type, res->data_version, res->version, res->memory_flags, res->data); } @@ -1673,7 +1673,7 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data) str8_deserial_read_struct(data, entry_offset, &coff_entry); // NOTE: this is not documented on MSDN but high bit here is set for some reason - U32 name_offset = coff_entry.name.offset & ~COFF_RESOURCE_SUB_DIR_FLAG; + U32 name_offset = coff_entry.name.offset & ~COFF_Resource_SubDirFlag; U16 name_size = 0; str8_deserial_read_struct(data, name_offset, &name_size); @@ -1681,15 +1681,15 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data) str8_deserial_read_block(data, name_offset + sizeof(name_size), name_size*sizeof(U16), &name_block); String16 name16 = str16((U16*)name_block.str, name_size); - B32 is_dir = !!(coff_entry.id.data_entry_offset & COFF_RESOURCE_SUB_DIR_FLAG); + B32 is_dir = !!(coff_entry.id.data_entry_offset & COFF_Resource_SubDirFlag); - entry->id.type = COFF_ResourceIDType_STRING; + entry->id.type = COFF_ResourceIDType_String; entry->id.u.string = str8_from_16(arena, name16); entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF; if (is_dir) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); - frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_RESOURCE_SUB_DIR_FLAG; + frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_Resource_SubDirFlag; frame->directory_ptr = &entry->u.dir; SLLStackPush(stack, frame); goto yeild; @@ -1710,15 +1710,15 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data) COFF_ResourceDirEntry coff_entry = {0}; str8_deserial_read_struct(data, entry_offset, &coff_entry); - B32 is_dir = !!(coff_entry.id.sub_dir_offset & COFF_RESOURCE_SUB_DIR_FLAG); + B32 is_dir = !!(coff_entry.id.sub_dir_offset & COFF_Resource_SubDirFlag); - entry->id.type = COFF_ResourceIDType_NUMBER; + entry->id.type = COFF_ResourceIDType_Number; entry->id.u.number = coff_entry.name.id; entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF; if (is_dir) { struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1); - frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_RESOURCE_SUB_DIR_FLAG; + frame->table_offset = coff_entry.id.sub_dir_offset & ~COFF_Resource_SubDirFlag; frame->directory_ptr = &entry->u.dir; SLLStackPush(stack, frame); goto yeild; @@ -1740,11 +1740,11 @@ internal String8 pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data) { COFF_ResourceID type = {0}; - type.type = COFF_ResourceIDType_NUMBER; + type.type = COFF_ResourceIDType_Number; type.u.number = PE_ResourceKind_MANIFEST; COFF_ResourceID id = {0}; - id.type = COFF_ResourceIDType_NUMBER; + id.type = COFF_ResourceIDType_Number; id.u.number = resource_id; String8 res = coff_write_resource(arena, type, id, 1, 0, 1033, 0, 0, manifest_data); diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index f0f97e8a..e47ebe6e 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -340,6 +340,7 @@ #include "mutable_text/mutable_text.h" #include "path/path.h" #include "coff/coff.h" +#include "coff/coff_parse.h" #include "pe/pe.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" @@ -381,6 +382,7 @@ #include "mutable_text/mutable_text.c" #include "path/path.c" #include "coff/coff.c" +#include "coff/coff_parse.c" #include "pe/pe.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" diff --git a/src/raddump/raddump.c b/src/raddump/raddump.c index f1cea0ee..ec47f263 100644 --- a/src/raddump/raddump.c +++ b/src/raddump/raddump.c @@ -228,7 +228,7 @@ rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input Temp scratch = scratch_begin(&arena, 1); char *input_type_string = "???"; - if (coff_is_archive(raw_data)) { + if (coff_is_regular_archive(raw_data)) { input_type_string = "Archive"; } else if (coff_is_thin_archive(raw_data)) { input_type_string = "Thin Archive"; @@ -360,9 +360,9 @@ rd_section_markers_from_coff_symbol_table(Arena *arena, String8 raw_data, U64 st COFF_Symbol32 *symbol = &symbols.v[symbol_idx]; COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); - B32 is_marker = interp == COFF_SymbolValueInterp_REGULAR && + B32 is_marker = interp == COFF_SymbolValueInterp_Regular && symbol->aux_symbol_count == 0 && - (symbol->storage_class == COFF_SymStorageClass_EXTERNAL || symbol->storage_class == COFF_SymStorageClass_STATIC); + (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static); if (is_marker) { String8 name = coff_read_symbol_name(raw_data, string_table_off, &symbol->name); @@ -411,7 +411,7 @@ rd_dw_sections_from_coff_section_table(Arena *arena, for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ions[i]; Rng1U64 raw_data_range = rng_1u64(header->foff, header->foff + header->fsize); - String8 name = coff_name_from_section_header(header, raw_image, string_table_off); + String8 name = coff_name_from_section_header(raw_image, header, string_table_off); DW_SectionKind s = DW_Section_Null; B32 is_dwo = 0; @@ -4496,7 +4496,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 B32 keep_parsing = 1; for (U64 i = 0; i < section_count && keep_parsing; ++i) { COFF_SectionHeader *header = §ions[i]; - String8 sect_name = coff_name_from_section_header(header, raw_image, string_table_off); + String8 sect_name = coff_name_from_section_header(raw_image, header, string_table_off); Rng1U64 sect_frange = rng_1u64(header->foff, header->foff+header->fsize); String8 raw_sect = str8_substr(raw_image, sect_frange); if (str8_match_lit(".debug$S", sect_name, 0)) { @@ -4544,7 +4544,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ions[i]; - String8 sect_name = coff_name_from_section_header(header, raw_image, string_table_off); + String8 sect_name = coff_name_from_section_header(raw_image, header, string_table_off); Rng1U64 sect_frange = rng_1u64(header->foff, header->foff+header->fsize); String8 raw_sect = str8_substr(raw_image, sect_frange); if (str8_match_lit(".debug$S", sect_name, 0)) { @@ -4577,7 +4577,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 // COFF internal void -coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ArchiveMemberHeader header, String8 long_names) +coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names) { Temp scratch = scratch_begin(&arena, 1); String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header.time_stamp); @@ -4608,12 +4608,12 @@ coff_print_seciton_table(Arena *arena, for (U64 i = 0; i < symbols.count; ++i) { COFF_Symbol32 *symbol = symbols.v+i; COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); - if (interp == COFF_SymbolValueInterp_REGULAR && + if (interp == COFF_SymbolValueInterp_Regular && symbol->aux_symbol_count == 0 && - (symbol->storage_class == COFF_SymStorageClass_EXTERNAL || symbol->storage_class == COFF_SymStorageClass_STATIC)) { + (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static)) { if (symbol->section_number > 0 && symbol->section_number <= symbols.count) { COFF_SectionHeader *header = sect_headers+(symbol->section_number-1); - if (header->flags & COFF_SectionFlag_LNK_COMDAT) { + if (header->flags & COFF_SectionFlag_LnkCOMDAT) { symlinks[symbol->section_number-1] = coff_read_symbol_name(raw_data, string_table_off, &symbol->name); } } @@ -4644,7 +4644,7 @@ coff_print_seciton_table(Arena *arena, COFF_SectionHeader *header = sect_headers+i; String8 name = str8_cstring_capped(header->name, header->name+sizeof(header->name)); - String8 full_name = coff_name_from_section_header(header, raw_data, string_table_off); + String8 full_name = coff_name_from_section_header(raw_data, header, string_table_off); String8 align; { @@ -4655,69 +4655,69 @@ coff_print_seciton_table(Arena *arena, String8 flags; { String8List mem_flags = {0}; - if (header->flags & COFF_SectionFlag_MEM_READ) { + if (header->flags & COFF_SectionFlag_MemRead) { str8_list_pushf(scratch.arena, &mem_flags, "r"); } - if (header->flags & COFF_SectionFlag_MEM_WRITE) { + if (header->flags & COFF_SectionFlag_MemWrite) { str8_list_pushf(scratch.arena, &mem_flags, "w"); } - if (header->flags & COFF_SectionFlag_MEM_EXECUTE) { + if (header->flags & COFF_SectionFlag_MemExecute) { str8_list_pushf(scratch.arena, &mem_flags, "x"); } String8List cnt_flags = {0}; - if (header->flags & COFF_SectionFlag_CNT_CODE) { + if (header->flags & COFF_SectionFlag_CntCode) { str8_list_pushf(scratch.arena, &cnt_flags, "c"); } - if (header->flags & COFF_SectionFlag_CNT_INITIALIZED_DATA) { + if (header->flags & COFF_SectionFlag_CntInitializedData) { str8_list_pushf(scratch.arena, &cnt_flags, "d"); } - if (header->flags & COFF_SectionFlag_CNT_UNINITIALIZED_DATA) { + if (header->flags & COFF_SectionFlag_CntUninitializedData) { str8_list_pushf(scratch.arena, &cnt_flags, "u"); } String8List mem_extra_flags = {0}; - if (header->flags & COFF_SectionFlag_MEM_SHARED) { + if (header->flags & COFF_SectionFlag_MemShared) { str8_list_pushf(scratch.arena, &mem_flags, "s"); } - if (header->flags & COFF_SectionFlag_MEM_16BIT) { + if (header->flags & COFF_SectionFlag_Mem16Bit) { str8_list_pushf(scratch.arena, &mem_extra_flags, "h"); } - if (header->flags & COFF_SectionFlag_MEM_LOCKED) { + if (header->flags & COFF_SectionFlag_MemLocked) { str8_list_pushf(scratch.arena, &mem_extra_flags, "l"); } - if (header->flags & COFF_SectionFlag_MEM_DISCARDABLE) { + if (header->flags & COFF_SectionFlag_MemDiscardable) { str8_list_pushf(scratch.arena, &mem_extra_flags, "d"); } - if (header->flags & COFF_SectionFlag_MEM_NOT_CACHED) { + if (header->flags & COFF_SectionFlag_MemNotCached) { str8_list_pushf(scratch.arena, &mem_extra_flags, "c"); } - if (header->flags & COFF_SectionFlag_MEM_NOT_PAGED) { + if (header->flags & COFF_SectionFlag_MemNotPaged) { str8_list_pushf(scratch.arena, &mem_extra_flags, "p"); } String8List lnk_flags = {0}; - if (header->flags & COFF_SectionFlag_LNK_REMOVE) { + if (header->flags & COFF_SectionFlag_LnkRemove) { str8_list_pushf(scratch.arena, &lnk_flags, "r"); } - if (header->flags & COFF_SectionFlag_LNK_COMDAT) { + if (header->flags & COFF_SectionFlag_LnkCOMDAT) { str8_list_pushf(scratch.arena, &lnk_flags, "c"); } - if (header->flags & COFF_SectionFlag_LNK_OTHER) { + if (header->flags & COFF_SectionFlag_LnkOther) { str8_list_pushf(scratch.arena, &lnk_flags, "o"); } - if (header->flags & COFF_SectionFlag_LNK_INFO) { + if (header->flags & COFF_SectionFlag_LnkInfo) { str8_list_pushf(scratch.arena, &lnk_flags, "i"); } - if (header->flags & COFF_SectionFlag_LNK_NRELOC_OVFL) { + if (header->flags & COFF_SectionFlag_LnkNRelocOvfl) { str8_list_pushf(scratch.arena, &lnk_flags, "f"); } String8List other_flags = {0}; - if (header->flags & COFF_SectionFlag_TYPE_NO_PAD) { + if (header->flags & COFF_SectionFlag_TypeNoPad) { str8_list_pushf(scratch.arena, &other_flags, "n"); } - if (header->flags & COFF_SectionFlag_GPREL) { + if (header->flags & COFF_SectionFlag_GpRel) { str8_list_pushf(scratch.arena, &other_flags, "g"); } @@ -4773,11 +4773,11 @@ coff_print_seciton_table(Arena *arena, rd_newline(); rd_printf("Flags:"); rd_indent(); - rd_printf("r = MEM_READ w = MEM_WRITE x = MEM_EXECUTE"); - rd_printf("c = CNT_CODE d = INITIALIZED_DATA u = UNINITIALIZED_DATA"); - rd_printf("s = MEM_SHARED h = MEM_16BIT l = MEM_LOCKED d = MEM_DISCARDABLE c = MEM_NOT_CACHED p = MEM_NOT_PAGED"); - rd_printf("r = LNK_REMOVE c = LNK_COMDAT o = LNK_OTHER i = LNK_INFO f = LNK_NRELOC_OVFL"); - rd_printf("g = GPREL n = TYPE_NO_PAD"); + rd_printf("r = MemRead w = MemWrite x = MemExecute"); + rd_printf("c = CntCode d = InitializedData u = UninitializedData"); + rd_printf("s = MemShared h = Mem16bit l = MemLocked d = MemDiscardable c = MemNotCached p = MemNotPaged"); + rd_printf("r = LnkRemove c = LnkComdat o = LnkOther i = LnkInfo f = LnkNRelocOvfl"); + rd_printf("g = GpRel n = TypeNoPad"); rd_unindent(); rd_unindent(); @@ -4802,7 +4802,7 @@ coff_disasm_sections(Arena *arena, if (section_count) { for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) { COFF_SectionHeader *sect = sections+sect_idx; - if (sect->flags & COFF_SectionFlag_CNT_CODE) { + if (sect->flags & COFF_SectionFlag_CntCode) { U64 sect_off = is_obj ? sect->foff : sect->voff; U64 sect_size = is_obj ? sect->fsize : sect->vsize; String8 raw_code = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size)); @@ -4950,10 +4950,10 @@ coff_print_symbol_table(Arena *arena, String8 storage_class = coff_string_from_sym_storage_class(symbol->storage_class); String8 section_number; switch (symbol->section_number) { - case COFF_SYMBOL_UNDEFINED_SECTION: section_number = str8_lit("UNDEF"); break; - case COFF_SYMBOL_ABS_SECTION: section_number = str8_lit("ABS"); break; - case COFF_SYMBOL_DEBUG_SECTION: section_number = str8_lit("DEBUG"); break; - default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break; + case COFF_Symbol_UndefinedSection: section_number = str8_lit("UNDEF"); break; + case COFF_Symbol_AbsSection32: section_number = str8_lit("ABS"); break; + case COFF_Symbol_DebugSection32: section_number = str8_lit("DEBUG"); break; + default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break; } String8List line = {0}; @@ -4973,28 +4973,28 @@ coff_print_symbol_table(Arena *arena, for (U64 k=i+1, c = i+symbol->aux_symbol_count; k <= c; ++k) { void *raw_aux = &symbols.v[k]; switch (symbol->storage_class) { - case COFF_SymStorageClass_EXTERNAL: { + case COFF_SymStorageClass_External: { COFF_SymbolFuncDef *func_def = (COFF_SymbolFuncDef*)&symbols.v[k]; rd_printf("Tag Index %#x, Total Size %#x, Line Numbers %#x, Next Function %#x", func_def->tag_index, func_def->total_size, func_def->ptr_to_ln, func_def->ptr_to_next_func); } break; - case COFF_SymStorageClass_FUNCTION: { + case COFF_SymStorageClass_Function: { COFF_SymbolFunc *func = raw_aux; rd_printf("Ordinal Line Number %#x, Next Function %#x", func->ln, func->ptr_to_next_func); } break; - case COFF_SymStorageClass_WEAK_EXTERNAL: { + case COFF_SymStorageClass_WeakExternal: { COFF_SymbolWeakExt *weak = raw_aux; String8 type = coff_string_from_weak_ext_type(weak->characteristics); rd_printf("Tag Index %#x, Characteristics %S", weak->tag_index, type); } break; - case COFF_SymStorageClass_FILE: { + case COFF_SymStorageClass_File: { COFF_SymbolFile *file = raw_aux; String8 name = str8_cstring_capped(file->name, file->name+sizeof(file->name)); rd_printf("Name %S", name); } break; - case COFF_SymStorageClass_STATIC: { + case COFF_SymStorageClass_Static: { COFF_SymbolSecDef *sd = raw_aux; - String8 selection = coff_string_from_selection(sd->selection); + String8 selection = coff_string_from_comdat_select_type(sd->selection); U32 number = sd->number_lo; if (is_big_obj) { number |= (U32)sd->number_hi << 16; @@ -5025,7 +5025,7 @@ coff_print_symbol_table(Arena *arena, } internal void -coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_HeaderBigObj *header) +coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header) { Temp scratch = scratch_begin(&arena, 1); @@ -5034,20 +5034,18 @@ coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_H rd_printf("# Big Obj"); rd_indent(); - - rd_printf("Time Stamp: %S", time_stamp ); - rd_printf("Machine: %S", machine ); - rd_printf("Section Count: %u", header->section_count ); + rd_printf("Time Stamp: %S", time_stamp ); + rd_printf("Machine: %S", machine ); + rd_printf("Section Count: %u", header->section_count ); rd_printf("Symbol Table: %#x", header->symbol_table_foff); - rd_printf("Symbol Count: %u", header->symbol_count ); - + rd_printf("Symbol Count: %u", header->symbol_count ); rd_unindent(); scratch_end(scratch); } internal void -coff_print_header(Arena *arena, String8List *out, String8 indent, COFF_Header *header) +coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header) { Temp scratch = scratch_begin(&arena, 1); @@ -5055,22 +5053,22 @@ coff_print_header(Arena *arena, String8List *out, String8 indent, COFF_Header *h String8 machine = coff_string_from_machine_type(header->machine); String8 flags = coff_string_from_flags(scratch.arena, header->flags); - rd_printf("# COFF Header"); + rd_printf("# COFF File Header"); rd_indent(); - rd_printf("Time Stamp: %S", time_stamp ); - rd_printf("Machine: %S", machine ); - rd_printf("Section Count: %u", header->section_count ); + rd_printf("Time Stamp: %S", time_stamp ); + rd_printf("Machine: %S", machine ); + rd_printf("Section Count: %u", header->section_count ); rd_printf("Symbol Table: %#x", header->symbol_table_foff ); - rd_printf("Symbol Count: %u", header->symbol_count ); - rd_printf("Optional Header Size: %m", header->optional_header_size); - rd_printf("Flags: %S", flags ); + rd_printf("Symbol Count: %u", header->symbol_count ); + rd_printf("Optional Header Size: %m", header->optional_header_size); + rd_printf("Flags: %S", flags ); rd_unindent(); scratch_end(scratch); } internal void -coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ImportHeader *header) +coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header) { Temp scratch = scratch_begin(&arena, 1); @@ -5079,15 +5077,15 @@ coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ImportHea rd_printf("# Import"); rd_indent(); - rd_printf("Version: %u", header->version ); - rd_printf("Machine: %S", machine ); - rd_printf("Time Stamp: %S", time_stamp ); - rd_printf("Data Size: %m", header->data_size); - rd_printf("Hint: %u", header->hint ); - rd_printf("Type: %u", header->type ); - rd_printf("Name Type: %u", header->name_type); - rd_printf("Function: %S", header->func_name); - rd_printf("DLL: %S", header->dll_name ); + rd_printf("Version: %u", header->version ); + rd_printf("Machine: %S", machine ); + rd_printf("Time Stamp: %S", time_stamp ); + rd_printf("Data Size: %m", header->data_size ); + rd_printf("Hint: %u", header->hint_or_ordinal); + rd_printf("Type: %u", header->type ); + rd_printf("Import By: %u", header->import_by ); + rd_printf("Function: %S", header->func_name ); + rd_printf("DLL: %S", header->dll_name ); rd_unindent(); scratch_end(scratch); @@ -5098,8 +5096,8 @@ coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_d { Temp scratch = scratch_begin(&arena, 1); - COFF_HeaderBigObj *big_obj = str8_deserial_get_raw_ptr(raw_data, 0, sizeof(COFF_HeaderBigObj)); - COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sizeof(COFF_HeaderBigObj), sizeof(COFF_SectionHeader)*big_obj->section_count); + COFF_BigObjHeader *big_obj = str8_deserial_get_raw_ptr(raw_data, 0, sizeof(COFF_BigObjHeader)); + COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sizeof(COFF_BigObjHeader), sizeof(COFF_SectionHeader)*big_obj->section_count); U64 string_table_off = big_obj->symbol_table_foff + sizeof(COFF_Symbol32)*big_obj->symbol_count; COFF_Symbol32Array symbols = coff_symbol_array_from_data_32(scratch.arena, raw_data, big_obj->symbol_table_foff, big_obj->symbol_count); @@ -5151,14 +5149,14 @@ coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, { Temp scratch = scratch_begin(&arena, 1); - COFF_Header *header = (COFF_Header *)raw_data.str; + COFF_FileHeader *header = (COFF_FileHeader *)raw_data.str; COFF_SectionHeader *sections = (COFF_SectionHeader *)(header+1); U64 string_table_off = header->symbol_table_foff + sizeof(COFF_Symbol16)*header->symbol_count; COFF_Symbol32Array symbols = coff_symbol_array_from_data_16(scratch.arena, raw_data, header->symbol_table_foff, header->symbol_count); Arch arch = arch_from_coff_machine(header->machine); if (opts & RD_Option_Headers) { - coff_print_header(arena, out, indent, header); + coff_print_file_header(arena, out, indent, header); rd_newline(); } @@ -5353,16 +5351,16 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a } switch (member_type) { - case COFF_DataType_BIG_OBJ: { - coff_print_big_obj(arena, out, indent, member.data, opts); - } break; - case COFF_DataType_OBJ: { + case COFF_DataType_Obj: { coff_print_obj(arena, out, indent, member.data, opts); } break; - case COFF_DataType_IMPORT: { + case COFF_DataType_BigObj: { + coff_print_big_obj(arena, out, indent, member.data, opts); + } break; + case COFF_DataType_Import: { if (opts & RD_Option_Headers) { - COFF_ImportHeader header = {0}; - U64 parse_size = coff_parse_archive_import(member.data, 0, &header); + COFF_ParsedArchiveImportHeader header = {0}; + U64 parse_size = coff_parse_import(member.data, 0, &header); if (parse_size) { coff_print_import(arena, out, indent, &header); } else { @@ -5370,7 +5368,7 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a } } } break; - case COFF_DataType_NULL: { + case COFF_DataType_Null: { rd_errorf("unknown member format", member_offset); } break; } @@ -6600,9 +6598,9 @@ pe_print_exceptions(Arena *arena, rd_indent(); rd_printf("%-8s %-8s %-8s %-8s", "Offset", "Begin", "End", "Unwind Info"); switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X64: - case COFF_MachineType_X86: { + case COFF_Machine_Unknown: break; + case COFF_Machine_X64: + case COFF_Machine_X86: { pe_print_exceptions_x8664(arena, out, indent, section_count, sections, raw_data, except_frange, rdi); } break; default: NotImplemented; break; @@ -6635,9 +6633,9 @@ pe_print_base_relocs(Arena *arena, U32 addr_size = 0; switch (machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: addr_size = 4; break; - case COFF_MachineType_X64: addr_size = 8; break; + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: addr_size = 4; break; + case COFF_Machine_X64: addr_size = 8; break; default: NotImplemented; } @@ -6667,9 +6665,9 @@ pe_print_base_relocs(Arena *arena, case PE_BaseRelocKind_DIR64: type_str = "DIR64"; break; default: { switch (machine) { - case COFF_MachineType_ARM: - case COFF_MachineType_ARM64: - case COFF_MachineType_ARMNT: { + case COFF_Machine_Arm: + case COFF_Machine_Arm64: + case COFF_Machine_ArmNt: { switch (type) { case PE_BaseRelocKind_ARM_MOV32: type_str = "ARM_MOV32"; break; case PE_BaseRelocKind_THUMB_MOV32: type_str = "THUMB_MOV32"; break; @@ -6718,14 +6716,14 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op goto exit; } - U64 coff_header_off = dos_header->coff_file_offset+sizeof(pe_magic); - COFF_Header *coff_header = str8_deserial_get_raw_ptr(raw_data, coff_header_off, sizeof(*coff_header)); - if (!coff_header) { + U64 file_header_off = dos_header->coff_file_offset+sizeof(pe_magic); + COFF_FileHeader *file_header = str8_deserial_get_raw_ptr(raw_data, file_header_off, sizeof(*file_header)); + if (!file_header) { rd_errorf("not enough bytes to read COFF header"); goto exit; } - U64 opt_header_off = coff_header_off + sizeof(*coff_header); + U64 opt_header_off = file_header_off + sizeof(*file_header); U16 opt_header_magic = 0; str8_deserial_read_struct(raw_data, opt_header_off, &opt_header_magic); if (opt_header_magic != PE_PE32_MAGIC && opt_header_magic != PE_PE32PLUS_MAGIC) { @@ -6733,36 +6731,36 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op goto exit; } - if (opt_header_magic == PE_PE32_MAGIC && coff_header->optional_header_size < sizeof(PE_OptionalHeader32)) { - rd_errorf("unexpected optional header size in COFF header %m, expected at least %m", coff_header->optional_header_size, sizeof(PE_OptionalHeader32)); + if (opt_header_magic == PE_PE32_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32)) { + rd_errorf("unexpected optional header size in COFF header %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32)); goto exit; } - if (opt_header_magic == PE_PE32PLUS_MAGIC && coff_header->optional_header_size < sizeof(PE_OptionalHeader32Plus)) { - rd_errorf("unexpected optional header size %m, expected at least %m", coff_header->optional_header_size, sizeof(PE_OptionalHeader32Plus)); + if (opt_header_magic == PE_PE32PLUS_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32Plus)) { + rd_errorf("unexpected optional header size %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32Plus)); goto exit; } - U64 sections_off = coff_header_off + sizeof(*coff_header) + coff_header->optional_header_size; - COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sections_off, sizeof(*sections)*coff_header->section_count); + U64 sections_off = file_header_off + sizeof(*file_header) + file_header->optional_header_size; + COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sections_off, sizeof(*sections)*file_header->section_count); if (!sections) { rd_errorf("not enough bytes to read COFF section headers"); goto exit; } - U64 string_table_off = coff_header->symbol_table_foff + sizeof(COFF_Symbol16) * coff_header->symbol_count; + U64 string_table_off = file_header->symbol_table_foff + sizeof(COFF_Symbol16) * file_header->symbol_count; - COFF_Symbol32Array symbols = coff_symbol_array_from_data_16(scratch.arena, raw_data, coff_header->symbol_table_foff, coff_header->symbol_count); + COFF_Symbol32Array symbols = coff_symbol_array_from_data_16(scratch.arena, raw_data, file_header->symbol_table_foff, file_header->symbol_count); - U8 *raw_opt_header = push_array(scratch.arena, U8, coff_header->optional_header_size); - str8_deserial_read_array(raw_data, opt_header_off, raw_opt_header, coff_header->optional_header_size); + U8 *raw_opt_header = push_array(scratch.arena, U8, file_header->optional_header_size); + str8_deserial_read_array(raw_data, opt_header_off, raw_opt_header, file_header->optional_header_size); if (opts & RD_Option_Headers) { - coff_print_header(arena, out, indent, coff_header); + coff_print_file_header(arena, out, indent, file_header); rd_newline(); } - Arch arch = arch_from_coff_machine(coff_header->machine); + Arch arch = arch_from_coff_machine(file_header->machine); U64 image_base = 0; U64 dir_count = 0; PE_DataDirectory *dirs = 0; @@ -6800,17 +6798,17 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op Rng1U64 *dirs_virt_ranges = push_array(scratch.arena, Rng1U64, dir_count); for (U64 i = 0; i < dir_count; ++i) { PE_DataDirectory dir = dirs[i]; - U64 file_off = coff_foff_from_voff(sections, coff_header->section_count, dir.virt_off); + U64 file_off = coff_foff_from_voff(sections, file_header->section_count, dir.virt_off); dirs_file_ranges[i] = r1u64(file_off, file_off+dir.virt_size); dirs_virt_ranges[i] = r1u64(dir.virt_off, dir.virt_off+dir.virt_size); } if (opts & RD_Option_Sections) { - coff_print_seciton_table(arena, out, indent, raw_data, string_table_off, symbols, coff_header->section_count, sections); + coff_print_seciton_table(arena, out, indent, raw_data, string_table_off, symbols, file_header->section_count, sections); } if (opts & RD_Option_Relocs) { - coff_print_relocs(arena, out, indent, raw_data, string_table_off, coff_header->machine, coff_header->section_count, sections, symbols); + coff_print_relocs(arena, out, indent, raw_data, string_table_off, file_header->machine, file_header->section_count, sections, symbols); } if (opts & RD_Option_Symbols) { @@ -6819,7 +6817,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op if (opts & RD_Option_Exports) { PE_ParsedExportTable exptab = pe_exports_from_data(arena, - coff_header->section_count, + file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXPORT], @@ -6829,8 +6827,8 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op if (opts & RD_Option_Imports) { B32 is_pe32 = opt_header_magic == PE_PE32_MAGIC; - PE_ParsedStaticImportTable static_imptab = pe_static_imports_from_data(arena, is_pe32, coff_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_IMPORT]); - PE_ParsedDelayImportTable delay_imptab = pe_delay_imports_from_data(arena, is_pe32, coff_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_DELAY_IMPORT]); + PE_ParsedStaticImportTable static_imptab = pe_static_imports_from_data(arena, is_pe32, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_IMPORT]); + PE_ParsedDelayImportTable delay_imptab = pe_delay_imports_from_data(arena, is_pe32, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_DELAY_IMPORT]); pe_print_static_import_table(arena, out, indent, image_base, static_imptab); pe_print_delay_import_table(arena, out, indent, image_base, delay_imptab); } @@ -6842,11 +6840,11 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op } if (opts & RD_Option_Exceptions) { - pe_print_exceptions(arena, out, indent, coff_header->machine, coff_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXCEPTIONS], rdi); + pe_print_exceptions(arena, out, indent, file_header->machine, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXCEPTIONS], rdi); } if (opts & RD_Option_Relocs) { - pe_print_base_relocs(arena, out, indent, coff_header->machine, image_base, coff_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_BASE_RELOC], rdi); + pe_print_base_relocs(arena, out, indent, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_BASE_RELOC], rdi); } if (opts & RD_Option_Debug) { @@ -6858,7 +6856,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op if (opts & RD_Option_Tls) { if (dim_1u64(dirs_file_ranges[PE_DataDirectoryIndex_TLS])) { - PE_ParsedTLS tls = pe_tls_from_data(scratch.arena, coff_header->machine, image_base, coff_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_TLS]); + PE_ParsedTLS tls = pe_tls_from_data(scratch.arena, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_TLS]); pe_print_tls(arena, out, indent, tls); } } @@ -6866,9 +6864,9 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op if (opts & RD_Option_LoadConfig) { String8 raw_lc = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_LOAD_CONFIG]); if (raw_lc.size) { - switch (coff_header->machine) { - case COFF_MachineType_UNKNOWN: break; - case COFF_MachineType_X86: { + switch (file_header->machine) { + case COFF_Machine_Unknown: break; + case COFF_Machine_X86: { PE_LoadConfig32 *lc = str8_deserial_get_raw_ptr(raw_lc, 0, sizeof(*lc)); if (lc) { pe_print_load_config32(arena, out, indent, lc); @@ -6876,7 +6874,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op rd_errorf("not enough bytes to parse 32bit load config"); } } break; - case COFF_MachineType_X64: { + case COFF_Machine_X64: { PE_LoadConfig64 *lc = str8_deserial_get_raw_ptr(raw_lc, 0, sizeof(*lc)); if (lc) { pe_print_load_config64(arena, out, indent, lc); @@ -6894,20 +6892,20 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op if (rdi) { section_markers = rd_section_markers_from_rdi(scratch.arena, rdi); } else { - section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_data, string_table_off, coff_header->section_count, symbols); + section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_data, string_table_off, file_header->section_count, symbols); } } if (opts & RD_Option_Rawdata) { - coff_raw_data_sections(arena, out, indent, raw_data, 0, section_markers, coff_header->section_count, sections); + coff_raw_data_sections(arena, out, indent, raw_data, 0, section_markers, file_header->section_count, sections); } if (opts & RD_Option_Disasm) { - coff_disasm_sections(arena, out, indent, raw_data, coff_header->machine, 0, 1, section_markers, coff_header->section_count, sections); + coff_disasm_sections(arena, out, indent, raw_data, file_header->machine, 0, 1, section_markers, file_header->section_count, sections); } if (opts & RD_Option_Dwarf) { - DW_SectionArray dwarf_sections = rd_dw_sections_from_coff_section_table(scratch.arena, raw_data, string_table_off, coff_header->section_count, sections); + DW_SectionArray dwarf_sections = rd_dw_sections_from_coff_section_table(scratch.arena, raw_data, string_table_off, file_header->section_count, sections); dw_format(arena, out, indent, opts, &dwarf_sections, arch, Image_CoffPe); } diff --git a/src/raddump/raddump.h b/src/raddump/raddump.h index 90738f38..29529060 100644 --- a/src/raddump/raddump.h +++ b/src/raddump/raddump.h @@ -120,7 +120,8 @@ typedef struct RD_Line // raddump -internal B32 rd_is_pe(String8 raw_data); +internal B32 rd_is_pe(String8 raw_data); + internal void rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data); // Markers @@ -134,12 +135,12 @@ internal RD_SectionArray rd_sections_from_coff_section_table(Arena *arnea, Strin // Disasm internal RD_DisasmResult rd_disasm_next_instruction(Arena *arena, Arch arch, U64 addr, String8 raw_code); -internal void rd_print_disasm (Arena *arena, String8List *out, String8 indent, Arch arch, U64 image_base, U64 sect_off, U64 marker_count, RD_Marker *markers, String8 raw_code); +internal void rd_print_disasm (Arena *arena, String8List *out, String8 indent, Arch arch, U64 image_base, U64 sect_off, U64 marker_count, RD_Marker *markers, String8 raw_code); // Raw Data internal String8 rd_format_hex_array(Arena *arena, U8 *ptr, U64 size); -internal void rd_print_raw_data (Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data); +internal void rd_print_raw_data (Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data); // DWARF @@ -182,15 +183,15 @@ internal void cv_print_symbols_section(Arena *arena, String8List *out, String8 i // COFF -internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ArchiveMemberHeader header, String8 long_names); +internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names); internal void coff_print_seciton_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, U64 string_table_off, COFF_Symbol32Array symbols, U64 sect_count, COFF_SectionHeader *sect_headers); -internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); -internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); +internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); +internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections); internal void coff_print_relocs (Arena *arena, String8List *out, String8 indent, String8 raw_data, U64 string_table_off, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols); internal void coff_print_symbol_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, U64 string_table_off, COFF_Symbol32Array symbols); -internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_HeaderBigObj *header); -internal void coff_print_header (Arena *arena, String8List *out, String8 indent, COFF_Header *header); -internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ImportHeader *header); +internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header); +internal void coff_print_file_header (Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header); +internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header); internal void coff_print_big_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); internal void coff_print_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts); internal void coff_print_archive (Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts); @@ -207,7 +208,7 @@ internal void pe_print_optional_header32plus(Arena *arena, String8List *out, Str internal void pe_print_load_config32 (Arena *arena, String8List *out, String8 indent, PE_LoadConfig32 *lc); internal void pe_print_load_config64 (Arena *arena, String8List *out, String8 indent, PE_LoadConfig64 *lc); internal void pe_print_tls (Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls); -internal void pe_print_debug_diretory (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir); +internal void pe_print_debug_diretory (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir); internal void pe_print_export_table (Arena *arena, String8List *out, String8 indent, PE_ParsedExportTable exptab); internal void pe_print_static_import_table (Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedStaticImportTable imptab); internal void pe_print_delay_import_table (Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedDelayImportTable imptab); diff --git a/src/raddump/raddump_main.c b/src/raddump/raddump_main.c index 0534911a..ea19187d 100644 --- a/src/raddump/raddump_main.c +++ b/src/raddump/raddump_main.c @@ -28,6 +28,7 @@ #include "path/path.h" #include "coff/coff.h" #include "coff/coff_enum.h" +#include "coff/coff_parse.h" #include "pe/pe.h" #include "msvc_crt/msvc_crt.h" #include "msvc_crt/msvc_crt_enum.h" @@ -53,6 +54,7 @@ #include "path/path.c" #include "coff/coff.c" #include "coff/coff_enum.c" +#include "coff/coff_parse.c" #include "pe/pe.c" #include "msvc_crt/msvc_crt.c" #include "msvc_crt/msvc_crt_enum.c" @@ -226,7 +228,7 @@ entry_point(CmdLine *cmdline) // format input rd_format_preamble(arena, out, indent, file_path, raw_data); - if (coff_is_archive(raw_data) || coff_is_thin_archive(raw_data)) { + if (coff_is_regular_archive(raw_data) || coff_is_thin_archive(raw_data)) { coff_print_archive(arena, out, indent, raw_data, opts); } else if (coff_is_big_obj(raw_data)) { coff_print_big_obj(arena, out, indent, raw_data, opts); diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 078740da..b396ab9b 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -161,15 +161,15 @@ internal RDI_BinarySectionFlags p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) { RDI_BinarySectionFlags result = 0; - if(flags & COFF_SectionFlag_MEM_READ) + if(flags & COFF_SectionFlag_MemRead) { result |= RDI_BinarySectionFlag_Read; } - if(flags & COFF_SectionFlag_MEM_WRITE) + if(flags & COFF_SectionFlag_MemWrite) { result |= RDI_BinarySectionFlag_Write; } - if(flags & COFF_SectionFlag_MEM_EXECUTE) + if(flags & COFF_SectionFlag_MemExecute) { result |= RDI_BinarySectionFlag_Execute; } diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c index d5de3918..9b2e49b5 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ b/src/rdi_from_pdb/rdi_from_pdb_main.c @@ -22,6 +22,7 @@ #include "async/async.h" #include "rdi_make/rdi_make_local.h" #include "coff/coff.h" +#include "coff/coff_parse.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" @@ -37,6 +38,7 @@ #include "async/async.c" #include "rdi_make/rdi_make_local.c" #include "coff/coff.c" +#include "coff/coff_parse.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c"