From 19fac9b1aaebd8e765efc286fd414f7e560cf82c Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Thu, 21 Nov 2024 19:42:39 -0800 Subject: [PATCH] changed symbol table parser to convert symbols as they are being read --- src/coff/coff.c | 14 +-- src/coff/coff.h | 51 +++++------ src/linker/lnk_obj.c | 207 +++++++++++++++++++++++-------------------- src/linker/lnk_obj.h | 2 +- 4 files changed, 145 insertions(+), 129 deletions(-) diff --git a/src/coff/coff.c b/src/coff/coff.c index 6c6e22ac..bdfca852 100644 --- a/src/coff/coff.c +++ b/src/coff/coff.c @@ -170,24 +170,24 @@ coff_section_flag_from_align_size(U64 align) } internal COFF_SymbolValueInterpType -coff_interp_symbol(COFF_Symbol32 *symbol) +coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class) { - if (symbol->storage_class == COFF_SymStorageClass_SECTION && symbol->section_number == COFF_SYMBOL_UNDEFINED_SECTION) { + if (storage_class == COFF_SymStorageClass_SECTION && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { return COFF_SymbolValueInterp_UNDEFINED; } - if (symbol->storage_class == COFF_SymStorageClass_EXTERNAL && symbol->value == 0 && symbol->section_number == COFF_SYMBOL_UNDEFINED_SECTION) { + if (storage_class == COFF_SymStorageClass_EXTERNAL && value == 0 && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { return COFF_SymbolValueInterp_UNDEFINED; } - if (symbol->storage_class == COFF_SymStorageClass_EXTERNAL && symbol->value != 0 && symbol->section_number == COFF_SYMBOL_UNDEFINED_SECTION) { + if (storage_class == COFF_SymStorageClass_EXTERNAL && value != 0 && section_number == COFF_SYMBOL_UNDEFINED_SECTION) { return COFF_SymbolValueInterp_COMMON; } - if (symbol->section_number == COFF_SYMBOL_ABS_SECTION) { + if (section_number == COFF_SYMBOL_ABS_SECTION) { return COFF_SymbolValueInterp_ABS; } - if (symbol->section_number == COFF_SYMBOL_DEBUG_SECTION) { + if (section_number == COFF_SYMBOL_DEBUG_SECTION) { return COFF_SymbolValueInterp_DEBUG; } - if (symbol->storage_class == COFF_SymStorageClass_WEAK_EXTERNAL) { + if (storage_class == COFF_SymStorageClass_WEAK_EXTERNAL) { return COFF_SymbolValueInterp_WEAK; } return COFF_SymbolValueInterp_REGULAR; diff --git a/src/coff/coff.h b/src/coff/coff.h index ee50abe5..866ea6b7 100644 --- a/src/coff/coff.h +++ b/src/coff/coff.h @@ -425,42 +425,39 @@ union COFF_SymbolName }long_name; }; +#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 +{ + struct + { + COFF_SymDType msb; + COFF_SymType lsb; + } u; + U16 v; +}; + typedef struct COFF_Symbol16 COFF_Symbol16; struct COFF_Symbol16 { - COFF_SymbolName name; - U32 value; - U16 section_number; - union - { - struct - { - COFF_SymDType msb; - COFF_SymType lsb; - }u; - U16 v; - }type; + COFF_SymbolName name; + U32 value; + U16 section_number; + COFF_SymbolType type; COFF_SymStorageClass storage_class; - U8 aux_symbol_count; + U8 aux_symbol_count; }; typedef struct COFF_Symbol32 COFF_Symbol32; struct COFF_Symbol32 { - COFF_SymbolName name; - U32 value; - U32 section_number; - union - { - struct - { - COFF_SymDType msb; - COFF_SymType lsb; - }u; - U16 v; - }type; + COFF_SymbolName name; + U32 value; + U32 section_number; + COFF_SymbolType type; COFF_SymStorageClass storage_class; - U8 aux_symbol_count; + U8 aux_symbol_count; }; // Auxilary symbols are allocated with fixed size so that symbol table could be maintaned as array of regular size. @@ -815,7 +812,7 @@ 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(COFF_Symbol32 *symbol); +internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class); 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); diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index fc44573c..01998927 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -339,11 +339,10 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) // parse coff obj COFF_HeaderInfo coff_info = coff_header_info_from_data(input->data); COFF_SectionHeader *coff_sect_arr = (COFF_SectionHeader *)(input->data.str + coff_info.section_array_off); - COFF_Symbol32Array coff_symbols = coff_symbol_array_from_data(scratch.arena, input->data, coff_info.symbol_off, coff_info.symbol_count, coff_info.symbol_size); + void *coff_symbols = input->data.str + coff_info.symbol_off; // handle machines we dont support - if (coff_info.machine != COFF_MachineType_UNKNOWN && - coff_info.machine != COFF_MachineType_X64) { + if (coff_info.machine != COFF_MachineType_UNKNOWN && coff_info.machine != COFF_MachineType_X64) { lnk_error(LNK_Error_UnsupportedMachine, "%S: %S machine is supported", input->path, coff_string_from_machine_type(coff_info.machine)); } @@ -422,7 +421,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, is_big_obj, task->function_pad_min, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_symbols, chunk_ptr_arr, master_common_block); + LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, is_big_obj, task->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); @@ -726,66 +725,92 @@ lnk_symbol_array_from_coff(Arena *arena, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, - COFF_Symbol32Array coff_symbols, + U64 coff_symbol_count, + void *coff_symbols, LNK_ChunkPtr *chunk_ptr_arr, LNK_Chunk *master_common_block) { LNK_SymbolArray symbol_array; - symbol_array.count = coff_symbols.count; + symbol_array.count = coff_symbol_count; symbol_array.v = push_array(arena, LNK_Symbol, symbol_array.count); - for (U64 symbol_idx = 0; symbol_idx < coff_symbols.count; ++symbol_idx) { - COFF_Symbol32 *coff_symbol = &coff_symbols.v[symbol_idx]; - LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; + for (U64 symbol_idx = 0; symbol_idx < coff_symbol_count; ++symbol_idx) { + String8 name; + U32 section_number; + U32 value; + COFF_SymStorageClass storage_class; + COFF_SymbolType type; + U64 aux_symbol_count; + void *aux_symbols; + if (is_big_obj) { + COFF_Symbol32 *coff_symbol32 = (COFF_Symbol32 *)coff_symbols + symbol_idx; + name = coff_read_symbol_name(coff_data, string_table_off, &coff_symbol32->name); + section_number = coff_symbol32->section_number; + value = coff_symbol32->value; + storage_class = coff_symbol32->storage_class; + type = coff_symbol32->type; + aux_symbol_count = coff_symbol32->aux_symbol_count; + aux_symbols = coff_symbol32 + 1; + } else { + COFF_Symbol16 *coff_symbol16 = (COFF_Symbol16 *)coff_symbols + symbol_idx; + name = coff_read_symbol_name(coff_data, string_table_off, &coff_symbol16->name); + section_number = coff_symbol16->section_number; + value = coff_symbol16->value; + storage_class = coff_symbol16->storage_class; + type = coff_symbol16->type; + aux_symbol_count = coff_symbol16->aux_symbol_count; + aux_symbols = coff_symbol16 + 1; - symbol->obj = obj; - - String8 name = coff_read_symbol_name(coff_data, string_table_off, &coff_symbol->name); + // promote special section numbers to 32 bit + if (section_number == COFF_SYMBOL_DEBUG_SECTION_16) { + section_number = COFF_SYMBOL_DEBUG_SECTION; + } else if (section_number == COFF_SYMBOL_ABS_SECTION_16) { + section_number = COFF_SYMBOL_ABS_SECTION; + } + } - // TODO: we convert 16-bit symbols and copy them to arena; symbols with short names - // are stored in the symbol itself and becuase converted symbols are pushed to scratch - // that memory is discarded after obj is processed - name = push_str8_copy(arena, name); - - COFF_SymbolValueInterpType interp = coff_interp_symbol(coff_symbol); + if (symbol_idx + aux_symbol_count > coff_symbol_count) { + lnk_error(LNK_Error_IllData, "%S: symbol %S has out of bounds aux symbol count %u", obj_path, name, aux_symbol_count); + } + + COFF_SymbolValueInterpType interp = coff_interp_symbol(section_number, value, storage_class); switch (interp) { case COFF_SymbolValueInterp_REGULAR: { - if (coff_symbol->section_number == 0 || coff_symbol->section_number > sect_count) { - lnk_error(LNK_Error_IllData, "%S: out ouf bounds section index in symbol \"%S (%u)\"", obj_path, name, coff_symbol->section_number); + if (section_number == 0 || section_number > sect_count) { + lnk_error(LNK_Error_IllData, "%S: out ouf bounds section index in symbol \"%S (%u)\"", obj_path, name, section_number); break; } - COFF_SectionHeader *coff_sect_header = &coff_sect_arr[coff_symbol->section_number - 1]; + COFF_SectionHeader *coff_sect_header = &coff_sect_arr[section_number-1]; - if (coff_symbol->value > coff_sect_header->fsize) { - lnk_error(LNK_Error_IllData, "%S: out of bounds section offset in symbol \"%S (%u)\"", obj_path, name, coff_symbol->value); + if (value > coff_sect_header->fsize) { + lnk_error(LNK_Error_IllData, "%S: out of bounds section offset in symbol \"%S (%u)\"", obj_path, name, value); break; } LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static; - if (coff_symbol->storage_class == COFF_SymStorageClass_EXTERNAL) { + if (storage_class == COFF_SymStorageClass_EXTERNAL) { visibility = LNK_DefinedSymbolVisibility_Extern; } LNK_DefinedSymbolFlags flags = 0; - if (coff_symbol->type.u.lsb == COFF_SymType_NULL && - coff_symbol->type.u.msb == COFF_SymDType_FUNC && - (coff_sect_header->flags & COFF_SectionFlag_CNT_CODE)) { + if (COFF_SymbolType_IsFunc(type)) { flags |= LNK_DefinedSymbolFlag_IsFunc; } - LNK_Chunk *chunk = chunk_ptr_arr[coff_symbol->section_number-1]; - U64 offset = coff_symbol->value; + LNK_Chunk *chunk = chunk_ptr_arr[section_number-1]; + U64 offset = value; COFF_ComdatSelectType selection = COFF_ComdatSelectType_ANY; U64 check_sum = 0; if (coff_sect_header->flags & COFF_SectionFlag_LNK_COMDAT) { - B32 has_static_def = coff_symbol->value == 0 && - coff_symbol->type.u.lsb == COFF_SymType_NULL && - coff_symbol->storage_class == COFF_SymStorageClass_STATIC && - coff_symbol->aux_symbol_count == 1; + B32 has_static_def = value == 0 && + type.u.lsb == COFF_SymType_NULL && + storage_class == COFF_SymStorageClass_STATIC && + aux_symbol_count == 1; if (has_static_def) { - COFF_SymbolSecDef *secdef = (COFF_SymbolSecDef *)(coff_symbol + 1); + COFF_SymbolSecDef *secdef = aux_symbols; + selection = secdef->selection; check_sum = secdef->check_sum; @@ -797,13 +822,10 @@ lnk_symbol_array_from_coff(Arena *arena, if (secdef_number == 0 || secdef_number > sect_count) { lnk_error(LNK_Error_IllData, "%S: symbol %u has out of bounds section definition number %u", name, symbol_idx, secdef_number); - break; } LNK_Chunk *head_chunk = chunk_ptr_arr[secdef_number-1]; - LNK_Chunk *associate_chunk = chunk_ptr_arr[coff_symbol->section_number-1]; - Assert(head_chunk->type == LNK_Chunk_Leaf); - Assert(associate_chunk->type == LNK_Chunk_Leaf); + LNK_Chunk *associate_chunk = chunk_ptr_arr[section_number-1]; lnk_chunk_associate(arena, head_chunk, associate_chunk); } } @@ -812,7 +834,7 @@ lnk_symbol_array_from_coff(Arena *arena, if (function_pad_min) { if ((flags & LNK_DefinedSymbolFlag_IsFunc)) { if (offset > 0) { - // convert leaf to list chunk + // convert leaf to list // // there is no way to know up front how many splits we have, // so lazily convert chunks when see two or more functions @@ -820,15 +842,15 @@ lnk_symbol_array_from_coff(Arena *arena, if (chunk->type == LNK_Chunk_Leaf) { // make a list chunk LNK_Chunk *chunk_list = push_array(arena, LNK_Chunk, 1); + chunk_list->type = LNK_Chunk_List; chunk_list->align = chunk->align; chunk_list->is_discarded = chunk->is_discarded; - chunk_list->type = LNK_Chunk_List; chunk_list->sort_idx = chunk->sort_idx; - chunk_list->sort_chunk = 0; chunk_list->input_idx = chunk->input_idx; chunk_list->flags = chunk->flags; chunk_list->associate = chunk->associate; chunk_list->u.list = push_array(arena, LNK_ChunkList, 1); + lnk_chunk_set_debugf(arena, chunk_list, "%S: function chunk list for %S", obj_path, name); // reset chunk properties chunk->align = 1; @@ -845,7 +867,7 @@ lnk_symbol_array_from_coff(Arena *arena, chunk = chunk_list; // set list chunk to be head of this section - chunk_ptr_arr[coff_symbol->section_number-1] = chunk_list; + chunk_ptr_arr[section_number-1] = chunk_list; } // find chunk that is near symbol @@ -853,16 +875,16 @@ lnk_symbol_array_from_coff(Arena *arena, LNK_ChunkNode *current = chunk->u.list->last; for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) { Assert(c->data->type == LNK_Chunk_Leaf); - if (cursor + c->data->u.leaf.size > coff_symbol->value) { + if (cursor + c->data->u.leaf.size > value) { current = c; break; } cursor += c->data->u.leaf.size; } - if (cursor < coff_symbol->value) { + if (cursor < value) { // bifurcate chunk at symbol offset - U64 split_pos = coff_symbol->value - cursor; + U64 split_pos = value - cursor; Rng1U64 left_data_range = rng_1u64(0, split_pos); Rng1U64 right_data_range = rng_1u64(left_data_range.max, current->data->u.leaf.size); String8 left_data = str8_substr(current->data->u.leaf, left_data_range); @@ -875,6 +897,7 @@ lnk_symbol_array_from_coff(Arena *arena, split_chunk->type = LNK_Chunk_Leaf; split_chunk->flags = current->data->flags; split_chunk->u.leaf = right_data; + lnk_chunk_set_debugf(arena, chunk, "%S: chunk split on function %S", obj_path, name); LNK_ChunkNode *split_node = push_array(arena, LNK_ChunkNode, 1); split_node->data = split_chunk; @@ -893,7 +916,7 @@ lnk_symbol_array_from_coff(Arena *arena, } else { // chunk was already split at the offset chunk = current->data; - offset = coff_symbol->value - cursor; + offset = value - cursor; } } @@ -905,7 +928,7 @@ lnk_symbol_array_from_coff(Arena *arena, if (chunk->type == LNK_Chunk_List) { U64 cursor = 0; for (LNK_ChunkNode *c = chunk->u.list->first; c != 0; c = c->next) { - if (cursor + c->data->u.leaf.size > coff_symbol->value) { + if (cursor + c->data->u.leaf.size > value) { chunk = c->data; offset = offset - cursor; break; @@ -916,57 +939,53 @@ lnk_symbol_array_from_coff(Arena *arena, } Assert(chunk->type == LNK_Chunk_Leaf); + LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; lnk_init_defined_symbol_chunk(symbol, name, visibility, flags, chunk, offset, selection, check_sum); - } break; - case COFF_SymbolValueInterp_UNDEFINED: { - lnk_init_undefined_symbol(symbol, name, LNK_SymbolScopeFlag_Main); - } break; - case COFF_SymbolValueInterp_COMMON: { - // :common_block - LNK_Chunk *chunk = push_array_no_zero(arena, LNK_Chunk, 1); - chunk->ref = lnk_chunk_ref(0,0); // :chunk_ref_assign - chunk->align = 1; - chunk->min_size = 0; - chunk->is_discarded = 0; - chunk->sort_chunk = 1; - chunk->type = LNK_Chunk_Leaf; - chunk->sort_idx = str8(0,0); - chunk->input_idx = LNK_MakeChunkInputIdx(0, lnk_chunk_list_get_node_count(master_common_block)); - chunk->flags = LNK_BSS_SECTION_FLAGS; - chunk->associate = 0; - chunk->u.leaf = str8(0, coff_symbol->value); - lnk_chunk_set_debugf(arena, chunk, "common block %S", name); - lnk_chunk_list_push(arena, master_common_block->u.list, chunk); - - LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Extern; - - LNK_DefinedSymbolFlags flags = 0; - if (coff_symbol->type.u.lsb == COFF_SymType_NULL && coff_symbol->type.u.msb == COFF_SymDType_FUNC) { - flags |= LNK_DefinedSymbolFlag_IsFunc; - } - - lnk_init_defined_symbol_chunk(symbol, name, visibility, flags, chunk, 0, COFF_ComdatSelectType_LARGEST, 0); + symbol->obj = obj; } break; case COFF_SymbolValueInterp_WEAK: { - if (coff_symbol->aux_symbol_count == 0 || symbol_idx + 1 >= coff_symbols.count) { + if (aux_symbol_count == 0) { lnk_error(LNK_Error_IllData, "%S: Weak symbol \"%S (%u)\" must at least one aux symbol", obj_path, name, symbol_idx); - break; } - COFF_SymbolWeakExt *weak_ext = (COFF_SymbolWeakExt*)(coff_symbol + 1); - if (weak_ext->tag_index >= symbol_array.count) { + COFF_SymbolWeakExt *weak_ext = aux_symbols; + if (weak_ext->tag_index >= coff_symbol_count) { lnk_error(LNK_Error_IllData, "%S: Weak symbol \"%S (%u)\" points to out of bounds symbol", obj_path, name, symbol_idx); break; } -#if 0 - if (symbol_array.v[weak_ext->tag_index] == NULL) { - lnk_error(LNK_ERROR_ILL_DATA, "%S: Weak symbol \"%S (%u)\" tags auxiliary symbol %u", - obj_path, name, symbol_idx, weak_ext->tag_index); - break; + + LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; + LNK_Symbol *fallback_symbol = &symbol_array.v[weak_ext->tag_index]; + lnk_init_weak_symbol(symbol, name, weak_ext->characteristics, fallback_symbol); + + symbol->obj = obj; + fallback_symbol->obj = obj; + } break; + case COFF_SymbolValueInterp_UNDEFINED: { + LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; + lnk_init_undefined_symbol(symbol, name, LNK_SymbolScopeFlag_Main); + symbol->obj = obj; + } break; + case COFF_SymbolValueInterp_COMMON: { + // :common_block + // + // TODO: sort chunks on size to reduce bss usage + LNK_Chunk *chunk = push_array(arena, LNK_Chunk, 1); + chunk->align = Min(32, u64_up_to_pow2(value)); // link.exe caps align at 32 bytes + chunk->type = LNK_Chunk_Leaf; + chunk->flags = master_common_block->flags; + chunk->u.leaf = str8(0, value); + lnk_chunk_set_debugf(arena, chunk, "%S: common block %S", obj_path, name); + lnk_chunk_list_push(arena, master_common_block->u.list, chunk); + + LNK_DefinedSymbolFlags flags = 0; + if (COFF_SymbolType_IsFunc(type)) { + flags |= LNK_DefinedSymbolFlag_IsFunc; } -#endif - - lnk_init_weak_symbol(symbol, name, weak_ext->characteristics, &symbol_array.v[weak_ext->tag_index]); + + LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; + lnk_init_defined_symbol_chunk(symbol, name, LNK_DefinedSymbolVisibility_Extern, flags, chunk, 0, COFF_ComdatSelectType_LARGEST, 0); + symbol->obj = obj; } break; case COFF_SymbolValueInterp_ABS: { // Never code or data, synthetic symbol. COFF spec says bits in value are used @@ -974,19 +993,19 @@ lnk_symbol_array_from_coff(Arena *arena, // LLVM uses undocumented mask 0x4800 on @feat.00 to tell if object was compiled with /guard:cf. LNK_DefinedSymbolVisibility visibility = LNK_DefinedSymbolVisibility_Static; - if (coff_symbol->storage_class == COFF_SymStorageClass_EXTERNAL) { + if (storage_class == COFF_SymStorageClass_EXTERNAL) { visibility = LNK_DefinedSymbolVisibility_Extern; } - lnk_init_defined_symbol_va(symbol, name, visibility, 0, coff_symbol->value); - } break; - case COFF_SymbolValueInterp_DEBUG: { - // ignore + LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; + lnk_init_defined_symbol_va(symbol, name, visibility, 0, value); + symbol->obj = obj; } break; + case COFF_SymbolValueInterp_DEBUG: break; } // skip aux symbols - symbol_idx += coff_symbol->aux_symbol_count; + symbol_idx += aux_symbol_count; } return symbol_array; diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index 3c27d3a7..bbdd5806 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -181,7 +181,7 @@ internal LNK_ChunkList * lnk_collect_obj_chunks(TP_Context *tp, TP_Arena *arena internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, LNK_SectionTable *st, U64 function_pad_min, U64 input_count, LNK_InputObj **inputs); internal LNK_Chunk * lnk_sect_chunk_array_from_coff(Arena *arena, U64 obj_id, String8 obj_path, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, String8 *sect_name_arr, String8 *sect_postfix_arr); -internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, LNK_Obj *obj, String8 obj_path, B32 is_big_obj, U64 function_pad_min, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, COFF_Symbol32Array coff_symbols, LNK_ChunkPtr *chunk_ptr_arr, LNK_Chunk *master_common_block); +internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, LNK_Obj *obj, String8 obj_path, B32 is_big_obj, U64 function_pad_min, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, U64 coff_symbol_count, void *coff_symbols, LNK_ChunkPtr *chunk_ptr_arr, LNK_Chunk *master_common_block); internal LNK_RelocList lnk_reloc_list_from_coff_reloc_array(Arena *arena, COFF_MachineType machine, LNK_Chunk *chunk, LNK_SymbolArray symbol_array, COFF_Reloc *reloc_v, U64 reloc_count); internal LNK_RelocList * lnk_reloc_list_array_from_coff(Arena *arena, COFF_MachineType machine, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, LNK_ChunkPtr *chunk_ptr_arr, LNK_SymbolArray symbol_array); internal LNK_DirectiveInfo lnk_init_directives(Arena *arena, String8 obj_path, U64 chunk_count, String8 *sect_name_arr, LNK_Chunk *chunk_arr);