diff --git a/src/linker/lnk.c b/src/linker/lnk.c index ab34c89b..8bee6700 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -3399,7 +3399,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_virtual_offsets_and_sizes_in_obj_section_headers if (~sect_header->flags & COFF_SectionFlag_LnkRemove) { LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx]; LNK_Section *sect = task->image_sects.v[sc->u.sect_idx]; - sect_header->vsize = lnk_size_from_section_contribution(sc); + sect_header->vsize = lnk_size_from_section_contrib(sc); sect_header->voff = sect->voff + sc->u.off; } } @@ -3423,7 +3423,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_file_offsets_and_sizes_in_obj_section_headers_ta LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx]; LNK_Section *sect = task->image_sects.v[sc->u.sect_idx]; if (~sect->flags & COFF_SectionFlag_CntUninitializedData) { - sect_header->fsize = lnk_size_from_section_contribution(sc); + sect_header->fsize = lnk_size_from_section_contrib(sc); sect_header->foff = sect->foff + sc->u.off; } } @@ -3885,7 +3885,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT LNK_BuildImageTask task = {0}; task.symtab = symtab; task.sectab = sectab; - task.default_align = lnk_default_align_from_machine(config->machine); + task.default_align = coff_default_align_from_machine(config->machine); task.objs_count = objs_count; task.objs = objs; task.sect_map = 0; @@ -4084,13 +4084,13 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT radsort(common_block_contribs, common_block_contribs_count, lnk_common_block_contrib_is_before); // compute .bss virtual size - this marks start of the common block - lnk_finalize_section_layout(sectab, common_block_sect, config->file_align); + lnk_finalize_section_layout(common_block_sect, config->file_align); U64 common_block_cursor = common_block_sect->vsize; // compute and assign offsets into the common block for (U64 contrib_idx = 0; contrib_idx < common_block_contribs_count; contrib_idx += 1) { LNK_CommonBlockContrib *contrib = &common_block_contribs[contrib_idx]; - U32 size = contrib->u.size; + U32 size = contrib->u.size; U32 align = Min(32, u64_up_to_pow2(size)); // link.exe caps align at 32 bytes common_block_cursor = AlignPow2(common_block_cursor, align); contrib->u.offset = common_block_cursor; @@ -4124,7 +4124,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT // assign contribs offsets, sizes, and section indices for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { - lnk_finalize_section_layout(sectab, §_n->data, config->file_align); + lnk_finalize_section_layout(§_n->data, config->file_align); } // remove empty sections @@ -4149,10 +4149,10 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT // assing layout offsets and sizes to merged sections for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) { LNK_Section *sect = §_n->data; - LNK_Section *final_sect = lnk_finalized_section_from_id(sectab, sect->merge_id); + LNK_Section *final_sect = sect->merge_dst; LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); - U64 last_sc_size = lnk_size_from_section_contribution(last_sc); + U64 last_sc_size = lnk_size_from_section_contrib(last_sc); sect->voff = final_sect->voff + first_sc->u.off; sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size; sect->foff = final_sect->foff + first_sc->u.off; @@ -4242,7 +4242,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT sc->align = 1; sc->u.obj_idx = max_U32; - lnk_finalize_section_layout(sectab, reloc, config->file_align); + lnk_finalize_section_layout(reloc, config->file_align); lnk_assign_section_virtual_space(reloc, config->sect_align, &voff_cursor); lnk_assign_section_index(reloc, sectab->next_sect_idx++); @@ -4273,7 +4273,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT image_header_sc->align = config->file_align; image_header_sc->data_list = image_header_data.first; - lnk_finalize_section_layout(sectab, image_header_sect, config->file_align); + lnk_finalize_section_layout(image_header_sect, config->file_align); } ProfBegin("Patch Section Symbols"); @@ -4301,7 +4301,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT // pick fill pick U8 fill_byte = 0; if (sect->flags & COFF_SectionFlag_CntCode) { - fill_byte = lnk_code_align_byte_from_machine(config->machine); + fill_byte = coff_code_align_byte_from_machine(config->machine); } // copy section contribution @@ -4314,7 +4314,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT Assert(sc->u.off >= prev_sc_opl); U64 fill_size = sc->u.off - prev_sc_opl; MemorySet(image_data.str + sect->foff + prev_sc_opl, fill_byte, fill_size); - prev_sc_opl = sc->u.off + lnk_size_from_section_contribution(sc); + prev_sc_opl = sc->u.off + lnk_size_from_section_contrib(sc); // copy contrib contents { @@ -4595,8 +4595,8 @@ lnk_build_rad_map(Arena *arena, String8 image_data, U64 thread_count, U64 objs_c U64 file_off = image_section_table[sc->u.sect_idx]->foff + sc->u.off; U64 virt_off = image_section_table[sc->u.sect_idx]->voff + sc->u.off; - U64 virt_size = lnk_size_from_section_contribution(sc); - U64 file_size = lnk_size_from_section_contribution(sc); + U64 virt_size = lnk_size_from_section_contrib(sc); + U64 file_size = lnk_size_from_section_contrib(sc); String8 sc_data = str8_substr(image_data, rng_1u64(file_off, file_off + virt_size)); U128 sc_hash = {0}; @@ -4804,16 +4804,13 @@ lnk_run(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) // if (config->rad_debug == LNK_SwitchState_Yes) { lnk_timer_begin(LNK_Timer_Rdi); - RDI_Arch arch = rdi_arch_from_coff_machine(config->machine); - LNK_SectionArray image_sects = lnk_section_table_get_output_sections(scratch.arena, image_ctx.sectab); String8List rdi_data = lnk_build_rad_debug_info(tp, tp_arena, config->target_os, - arch, + rdi_arch_from_coff_machine(config->machine), config->image_name, image_ctx.image_data, - image_sects, input.count, input.obj_arr, input.debug_s_arr, diff --git a/src/linker/lnk.h b/src/linker/lnk.h index 29128877..55facdc0 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -14,12 +14,32 @@ typedef struct LNK_LinkContext LNK_LibList lib_index[LNK_InputSource_Count]; } LNK_LinkContext; +// -- Image -------------------------------------------------------------------- + typedef struct LNK_ImageContext { String8 image_data; LNK_SectionTable *sectab; } LNK_ImageContext; +typedef struct LNK_SectionDefinition +{ + String8 name; + COFF_SectionFlags flags; + U64 contribs_count; + struct LNK_Obj *obj; + U64 obj_sect_idx; +} LNK_SectionDefinition; + +typedef struct LNK_CommonBlockContrib +{ + struct LNK_Symbol *symbol; + union { + U32 size; + U32 offset; + } u; +} LNK_CommonBlockContrib; + // --- Base Reloc -------------------------------------------------------------- typedef struct LNK_BaseRelocPage diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index b2fb9f30..031e9a8a 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -4440,11 +4440,11 @@ lnk_type_from_itype(CV_TypeIndex itype, Rng1U64 tpi_itype_range, RDIB_Type **tpi } internal U64 -lnk_voff_from_sect_off(U64 sect_idx, U64 sect_off, LNK_SectionArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) +lnk_voff_from_sect_off(U64 sect_idx, U64 sect_off, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) { U64 voff = 0; if (sect_idx < image_sects.count) { - voff = image_sects.v[sect_idx]->voff + sect_off; + voff = image_sects.v[sect_idx].voff + sect_off; } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", sect_idx, cv_string_from_sym_kind(symbol_kind), symbol_offset); @@ -4453,11 +4453,11 @@ lnk_voff_from_sect_off(U64 sect_idx, U64 sect_off, LNK_SectionArray image_sects, } internal Rng1U64 -lnk_virt_range_from_sect_off_size(U64 sect_idx, U64 sect_off, U64 size, LNK_SectionArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) +lnk_virt_range_from_sect_off_size(U64 sect_idx, U64 sect_off, U64 size, COFF_SectionHeaderArray image_sects, LNK_Obj *obj, CV_SymKind symbol_kind, U64 symbol_offset) { Rng1U64 virt_range = {0}; if (sect_idx < image_sects.count) { - U64 voff = image_sects.v[sect_idx]->voff + sect_off; + U64 voff = image_sects.v[sect_idx].voff + sect_off; virt_range = rng_1u64(voff, voff + size); } else { lnk_error_obj(LNK_Error_CvIllSymbolData, obj, "Out of bounds section index 0x%x in S_%S @ 0x%llx.", @@ -4590,8 +4590,8 @@ THREAD_POOL_TASK_FUNC(lnk_convert_line_tables_to_rdi_task) lnk_error_obj(LNK_Warning_IllData, obj, "Out of bounds section index (%u) in $$LINES; skip line info for \"%S\".", parsed_lines.sec_idx, file_path); continue; } - LNK_Section *sect = task->image_sects.v[parsed_lines.sec_idx]; - CV_LineArray lines = cv_c13_line_array_from_data(arena, raw_lines, sect->voff, parsed_lines); + COFF_SectionHeader *sect = &task->image_sects.v[parsed_lines.sec_idx]; + CV_LineArray lines = cv_c13_line_array_from_data(arena, raw_lines, sect->voff, parsed_lines); // find source file for this line table String8 normal_path = lnk_normalize_src_file_path(scratch.arena, file_path); @@ -5362,7 +5362,6 @@ lnk_build_rad_debug_info(TP_Context *tp, RDI_Arch arch, String8 image_name, String8 image_data, - LNK_SectionArray image_sects, U64 obj_count, LNK_Obj *obj_arr, CV_DebugS *debug_s_arr, @@ -5372,15 +5371,24 @@ lnk_build_rad_debug_info(TP_Context *tp, CV_DebugT types[CV_TypeIndexSource_COUNT]) { ProfBegin("RDI"); - Temp scratch = scratch_begin(0,0); + Temp scratch = scratch_begin(tp_arena->v,tp_arena->count); RDIB_Input input = rdib_init_input(scratch.arena); + COFF_SectionHeaderArray image_sects; + String8 image_strtab; + { + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, image_data); + image_sects.count = pe.section_count; + image_sects.v = (COFF_SectionHeader *)str8_substr(image_data, pe.section_table_range).str; + image_strtab = str8_substr(image_data, pe.string_table_range); + } + ProfBegin("Top Level Info"); { U64 image_vsize = 0; for (U64 sect_idx = 0; sect_idx < image_sects.count; sect_idx++) { - LNK_Section *sect = image_sects.v[sect_idx]; + COFF_SectionHeader *sect = &image_sects.v[sect_idx]; image_vsize = Max(image_vsize, sect->voff + sect->vsize); } @@ -5397,10 +5405,11 @@ lnk_build_rad_debug_info(TP_Context *tp, input.sect_count = image_sects.count; input.sections = push_array(scratch.arena, RDIB_BinarySection, image_sects.count); for (U64 sect_idx = 0; sect_idx < image_sects.count; ++sect_idx) { - LNK_Section *src = image_sects.v[sect_idx]; + COFF_SectionHeader *src = &image_sects.v[sect_idx]; RDIB_BinarySection *dst = &input.sections[sect_idx]; + String8 sect_name = coff_name_from_section_header(image_strtab, src); - dst->name = push_str8_copy(scratch.arena, src->name); + dst->name = push_str8_copy(scratch.arena, sect_name); dst->flags = rdi_binary_section_flags_from_coff_section_flags(src->flags); dst->voff_first = src->voff; dst->voff_opl = src->voff + src->vsize; diff --git a/src/linker/lnk_debug_info.h b/src/linker/lnk_debug_info.h index 7f08f7da..4ed75c34 100644 --- a/src/linker/lnk_debug_info.h +++ b/src/linker/lnk_debug_info.h @@ -453,7 +453,7 @@ typedef struct typedef struct { - LNK_SectionArray image_sects; + COFF_SectionHeaderArray image_sects; LNK_Obj *obj_arr; CV_DebugS *debug_s_arr; CV_DebugT ipi; @@ -555,7 +555,6 @@ internal String8List lnk_build_rad_debug_info(TP_Context *tp, RDI_Arch arch, String8 image_name, String8 image_data, - LNK_SectionArray image_sects, U64 obj_count, LNK_Obj *obj_arr, CV_DebugS *debug_s_arr, diff --git a/src/linker/lnk_section_table.c b/src/linker/lnk_section_table.c index 07ea2b00..c441c401 100644 --- a/src/linker/lnk_section_table.c +++ b/src/linker/lnk_section_table.c @@ -1,36 +1,6 @@ // Copyright (c) 2025 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -internal U8 -lnk_code_align_byte_from_machine(COFF_MachineType machine) -{ - U8 align_byte = 0; - switch (machine) { - case COFF_MachineType_X64: - case COFF_MachineType_X86: { - align_byte = 0xCC; - } break; - default: { - lnk_not_implemented("TODO: set align value for machine %S", coff_string_from_machine_type(machine)); - } break; - } - return align_byte; -} - -internal U16 -lnk_default_align_from_machine(COFF_MachineType machine) -{ - U16 align = 0; - switch (machine) { - case COFF_MachineType_Unknown: break; - case COFF_MachineType_X64: { - align = 16; - } break; - default: { NotImplemented; } break; - } - return align; -} - internal LNK_SectionContrib * lnk_section_contrib_chunk_push(LNK_SectionContribChunk *chunk, U64 count) { @@ -100,75 +70,16 @@ lnk_section_array_from_list(Arena *arena, LNK_SectionList list) return result; } -internal U64 -lnk_size_from_section_contribution(LNK_SectionContrib *sc) +internal String8 +lnk_make_name_with_flags(Arena *arena, String8 name, COFF_SectionFlags flags) { - U64 size = 0; - for (String8Node *n = sc->data_list; n != 0; n = n->next) { - size += n->string.size; - } - return size; -} - -internal U64 -lnk_voff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) -{ - COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; - U64 voff = sect_header->voff + sc->u.off; - return voff; -} - -internal U64 -lnk_foff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) -{ - COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; - U64 foff = sect_header->foff + sc->u.off; - return foff; -} - -internal U64 -lnk_fopl_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) -{ - U64 foff = lnk_foff_from_section_contrib(image_section_table, sc); - return foff + lnk_size_from_section_contribution(sc); -} - -internal LNK_SectionContrib * -lnk_get_first_section_contrib(LNK_Section *sect) -{ - if (sect->contribs.chunk_count > 0) { - if (sect->contribs.first->count > 0) { - return sect->contribs.first->v[0]; - } - } - return 0; -} - -internal LNK_SectionContrib * -lnk_get_last_section_contrib(LNK_Section *sect) -{ - if (sect->contribs.chunk_count > 0) { - if (sect->contribs.last->count > 0) { - return sect->contribs.last->v[sect->contribs.last->count-1]; - } - } - return 0; -} - -internal U64 -lnk_get_section_contrib_size(LNK_Section *sect) -{ - LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); - LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); - U64 size = (last_sc->u.off - first_sc->u.off) + lnk_size_from_section_contribution(last_sc); - return size; -} - -internal U64 -lnk_get_first_section_contrib_voff(COFF_SectionHeader **image_section_table, LNK_Section *sect) -{ - LNK_SectionContrib *sc = lnk_get_first_section_contrib(sect); - return lnk_voff_from_section_contrib(image_section_table, sc); + Temp scratch = scratch_begin(&arena, 1); + String8List l = {0}; + str8_list_push(scratch.arena, &l, name); + str8_list_push(scratch.arena, &l, str8_struct(&flags)); + String8 name_with_flags = str8_list_join(arena, &l, 0); + scratch_end(scratch); + return name_with_flags; } internal LNK_SectionTable * @@ -184,27 +95,15 @@ lnk_section_table_alloc(void) } internal void -lnk_section_table_release(LNK_SectionTable **st_ptr) +lnk_section_table_release(LNK_SectionTable **sectab_ptr) { ProfBeginFunction(); - LNK_SectionTable *sectab = *st_ptr; + LNK_SectionTable *sectab = *sectab_ptr; arena_release(sectab->arena); - *st_ptr = 0; + *sectab_ptr = 0; ProfEnd(); } -internal String8 -lnk_make_name_with_flags(Arena *arena, String8 name, COFF_SectionFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List l = {0}; - str8_list_push(scratch.arena, &l, name); - str8_list_push(scratch.arena, &l, str8_struct(&flags)); - String8 name_with_flags = str8_list_join(arena, &l, 0); - scratch_end(scratch); - return name_with_flags; -} - internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags) { @@ -212,9 +111,8 @@ lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags LNK_SectionNode *sect_node = push_array(sectab->arena, LNK_SectionNode, 1); LNK_Section *sect = §_node->data; - sect->id = sectab->id_max++; - sect->name = push_str8_copy(sectab->arena, name); - sect->flags = flags; + sect->name = push_str8_copy(sectab->arena, name); + sect->flags = flags; LNK_SectionList *sect_list = §ab->list; SLLQueuePush(sect_list->first, sect_list->last, sect_node); @@ -277,12 +175,12 @@ lnk_section_table_search(LNK_SectionTable *sectab, String8 full_or_partial_name, { Temp scratch = scratch_begin(0,0); - String8 name = {0}; + String8 name = {0}; String8 postfix = {0}; coff_parse_section_name(full_or_partial_name, &name, &postfix); - String8 name_with_flags = lnk_make_name_with_flags(scratch.arena, name, flags); - LNK_Section *section= 0; + String8 name_with_flags = lnk_make_name_with_flags(scratch.arena, name, flags); + LNK_Section *section = 0; hash_table_search_string_raw(sectab->sect_ht, name_with_flags, §ion); scratch_end(scratch); @@ -292,7 +190,7 @@ lnk_section_table_search(LNK_SectionTable *sectab, String8 full_or_partial_name, internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name) { - String8 name = {0}; + String8 name = {0}; String8 postfix = {0}; coff_parse_section_name(full_or_partial_name, &name, &postfix); @@ -325,7 +223,6 @@ lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_l ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); - LNK_Section **src_dst = push_array(scratch.arena, LNK_Section *, sectab->id_max); for (LNK_MergeDirectiveNode *merge_node = merge_list.first; merge_node != 0; merge_node = merge_node->next) { LNK_MergeDirective *merge = &merge_node->data; @@ -361,8 +258,8 @@ lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_l // are we trying to merge section that was already merged? LNK_Section *merge_sect = 0; hash_table_search_string_raw(sectab->sect_ht, merge->src, &merge_sect); - if (merge_sect && merge_sect->is_merged) { - LNK_Section *dst = src_dst[merge_sect->id]; + if (merge_sect && merge_sect->merge_dst) { + LNK_Section *dst = merge_sect->merge_dst; B32 is_ambiguous_merge = !str8_match(dst->name, merge->dst, 0); if (is_ambiguous_merge) { lnk_error(LNK_Warning_AmbiguousMerge, "Detected ambiguous section merge:"); @@ -398,13 +295,9 @@ lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_l for (U64 src_idx = 0; src_idx < src_matches.count; src_idx += 1) { LNK_Section *src = src_matches.v[src_idx]; - // update map - src_dst[src->id] = dst; - // merge section with destination lnk_section_contrib_chunk_list_concat_in_place(&dst->contribs, &src->contribs); - src->is_merged = 1; - src->merge_id = dst->id; + src->merge_dst = dst; // remove from output section list LNK_SectionNode *merge_node = lnk_section_table_remove(sectab, src->name); @@ -418,25 +311,6 @@ lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_l ProfEnd(); } -internal LNK_SectionArray -lnk_section_table_get_output_sections(Arena *arena, LNK_SectionTable *sectab) -{ - LNK_SectionArray result = {0}; - result.count = 0; - result.v = push_array(arena, LNK_Section *, sectab->list.count); - - for (LNK_SectionNode *sect_node = sectab->list.first; sect_node != 0; sect_node = sect_node->next) { - Assert(result.count < sectab->list.count); - result.v[result.count] = §_node->data; - result.count += 1; - } - - U64 unused_entry_count = sectab->list.count - result.count; - arena_pop(arena, unused_entry_count * sizeof(result.v[0])); - - return result; -} - internal int lnk_section_contrib_chunk_is_before(void *raw_a, void *raw_b) { @@ -445,7 +319,7 @@ lnk_section_contrib_chunk_is_before(void *raw_a, void *raw_b) } internal void -lnk_finalize_section_layout(LNK_SectionTable *sectab, LNK_Section *sect, U64 file_align) +lnk_finalize_section_layout(LNK_Section *sect, U64 file_align) { Temp scratch = scratch_begin(0,0); @@ -459,7 +333,7 @@ lnk_finalize_section_layout(LNK_SectionTable *sectab, LNK_Section *sect, U64 fil // repopulate chunk list in sorted order sect->contribs.first = 0; - sect->contribs.last = 0; + sect->contribs.last = 0; for (U64 chunk_idx = 0; chunk_idx < sect->contribs.chunk_count; chunk_idx += 1) { SLLQueuePush(sect->contribs.first, sect->contribs.last, chunks[chunk_idx]); } @@ -478,7 +352,7 @@ lnk_finalize_section_layout(LNK_SectionTable *sectab, LNK_Section *sect, U64 fil U64 sc_off = cursor; // compute contrib size - U64 sc_size = lnk_size_from_section_contribution(sc); + U64 sc_size = lnk_size_from_section_contrib(sc); cursor += sc_size; // assign offset and size @@ -495,7 +369,6 @@ lnk_finalize_section_layout(LNK_SectionTable *sectab, LNK_Section *sect, U64 fil scratch_end(scratch); } - internal void lnk_assign_section_index(LNK_Section *sect, U64 sect_idx) { @@ -526,22 +399,73 @@ lnk_assign_section_file_space(LNK_Section *sect, U64 *foff_cursor) } } -internal LNK_Section * -lnk_finalized_section_from_id(LNK_SectionTable *sectab, U64 id) +internal U64 +lnk_size_from_section_contrib(LNK_SectionContrib *sc) { - for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { - if (sect_n->data.id == id) { - return §_n->data; + U64 size = 0; + for (String8Node *n = sc->data_list; n != 0; n = n->next) { + size += n->string.size; + } + return size; +} + +internal U64 +lnk_voff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) +{ + COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; + U64 voff = sect_header->voff + sc->u.off; + return voff; +} + +internal U64 +lnk_foff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) +{ + COFF_SectionHeader *sect_header = image_section_table[sc->u.sect_idx+1]; + U64 foff = sect_header->foff + sc->u.off; + return foff; +} + +internal U64 +lnk_fopl_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc) +{ + U64 foff = lnk_foff_from_section_contrib(image_section_table, sc); + return foff + lnk_size_from_section_contrib(sc); +} + +internal LNK_SectionContrib * +lnk_get_first_section_contrib(LNK_Section *sect) +{ + if (sect->contribs.chunk_count > 0) { + if (sect->contribs.first->count > 0) { + return sect->contribs.first->v[0]; } } - - for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) { - if (sect_n->data.id == id) { - return lnk_finalized_section_from_id(sectab, sect_n->data.merge_id); - } - } - return 0; } +internal LNK_SectionContrib * +lnk_get_last_section_contrib(LNK_Section *sect) +{ + if (sect->contribs.chunk_count > 0) { + if (sect->contribs.last->count > 0) { + return sect->contribs.last->v[sect->contribs.last->count-1]; + } + } + return 0; +} +internal U64 +lnk_get_section_contrib_size(LNK_Section *sect) +{ + LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); + LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); + U64 size = (last_sc->u.off - first_sc->u.off) + lnk_size_from_section_contrib(last_sc); + return size; +} + +internal U64 +lnk_get_first_section_contrib_voff(COFF_SectionHeader **image_section_table, LNK_Section *sect) +{ + LNK_SectionContrib *sc = lnk_get_first_section_contrib(sect); + return lnk_voff_from_section_contrib(image_section_table, sc); +} diff --git a/src/linker/lnk_section_table.h b/src/linker/lnk_section_table.h index 14b2bbf8..7cd12460 100644 --- a/src/linker/lnk_section_table.h +++ b/src/linker/lnk_section_table.h @@ -20,18 +20,9 @@ typedef struct LNK_SectionContrib U8 unused[2]; }; } u; - U16 align; // alignment of the contribution in the image + U16 align; // contribution alignment in the image } LNK_SectionContrib; -typedef struct LNK_CommonBlockContrib -{ - struct LNK_Symbol *symbol; - union { - U32 size; - U32 offset; - } u; -} LNK_CommonBlockContrib; - typedef struct LNK_SectionContribChunk { struct LNK_SectionContribChunk *next; @@ -49,24 +40,14 @@ typedef struct LNK_SectionContribChunkList LNK_SectionContribChunk *last; } LNK_SectionContribChunkList; -typedef struct LNK_SectionDefinition -{ - String8 name; - COFF_SectionFlags flags; - U64 contribs_count; - struct LNK_Obj *obj; - U64 obj_sect_idx; -} LNK_SectionDefinition; - typedef struct LNK_Section { - U64 id; String8 name; COFF_SectionFlags flags; - B32 is_merged; - U64 merge_id; LNK_SectionContribChunkList contribs; + struct LNK_Section *merge_dst; + U64 voff; U64 vsize; U64 fsize; @@ -97,23 +78,44 @@ typedef struct LNK_SectionArray typedef struct LNK_SectionTable { Arena *arena; - U64 id_max; - U64 next_sect_idx; LNK_SectionList list; LNK_SectionList merge_list; - HashTable *sect_ht; // name -> LNK_Section * + HashTable *sect_ht; // (name * COFF_SectionFlags) -> LNK_Section * + U64 next_sect_idx; } LNK_SectionTable; -//////////////////////////////// +// --- Section Contrib Chunk List ---------------------------------------------- -internal U8 lnk_code_align_byte_from_machine(COFF_MachineType machine); -internal U16 lnk_default_align_from_machine(COFF_MachineType machine); +internal LNK_SectionContrib * lnk_section_contrib_chunk_push(LNK_SectionContribChunk *chunk, U64 count); +internal LNK_SectionContrib * lnk_section_contrib_chunk_push_atomic(LNK_SectionContribChunk *chunk, U64 count); +internal LNK_SectionContribChunk * lnk_section_contrib_chunk_list_push_chunk(Arena *arena, LNK_SectionContribChunkList *list, U64 cap, String8 sort_idx); +internal void lnk_section_contrib_chunk_list_concat_in_place(LNK_SectionContribChunkList *list, LNK_SectionContribChunkList *to_concat); +internal LNK_SectionContribChunk ** lnk_array_from_section_contrib_chunk_list(Arena *arena, LNK_SectionContribChunkList list); -//////////////////////////////// +// --- Section List ------------------------------------------------------------ internal LNK_SectionArray lnk_section_array_from_list(Arena *arena, LNK_SectionList list); -//////////////////////////////// +// --- Section Table ----------------------------------------------------------- + +internal String8 lnk_make_name_with_flags(Arena *arena, String8 name, COFF_SectionFlags flags); + +internal LNK_SectionTable * lnk_section_table_alloc(void); +internal void lnk_section_table_release(LNK_SectionTable **sectab_ptr); +internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); +internal LNK_SectionNode * lnk_section_table_remove(LNK_SectionTable *sectab, String8 name); +internal LNK_Section * lnk_section_table_search(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); +internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name); +internal void lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_list); + +// --- Section Finalization ---------------------------------------------------- + +internal void lnk_finalize_section_layout (LNK_Section *sect, U64 file_align); +internal void lnk_assign_section_index (LNK_Section *sect, U64 sect_idx); +internal void lnk_assign_section_virtual_space(LNK_Section *sect, U64 sect_align, U64 *voff_cursor); +internal void lnk_assign_section_file_space (LNK_Section *sect, U64 *foff_cursor); + +// --- Section Contribution ---------------------------------------------------- internal U64 lnk_size_from_section_contrib(LNK_SectionContrib *sc); internal U64 lnk_voff_from_section_contrib(COFF_SectionHeader **image_section_table, LNK_SectionContrib *sc); @@ -124,21 +126,3 @@ internal LNK_SectionContrib * lnk_get_first_section_contrib(LNK_Section *sect); internal LNK_SectionContrib * lnk_get_last_section_contrib(LNK_Section *sect); internal U64 lnk_get_section_contrib_size(LNK_Section *sect); internal U64 lnk_get_first_section_contrib_voff(COFF_SectionHeader **image_section_table, LNK_Section *sect); - -//////////////////////////////// - -internal LNK_SectionTable * lnk_section_table_alloc(void); -internal void lnk_section_table_release(LNK_SectionTable **st_ptr); -internal LNK_Section * lnk_section_table_push(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); -internal LNK_SectionNode * lnk_section_table_remove(LNK_SectionTable *sectab, String8 name); -internal LNK_Section * lnk_section_table_search(LNK_SectionTable *sectab, String8 name, COFF_SectionFlags flags); -internal LNK_SectionArray lnk_section_table_search_many(Arena *arena, LNK_SectionTable *sectab, String8 full_or_partial_name); -internal void lnk_section_table_merge(LNK_SectionTable *sectab, LNK_MergeDirectiveList merge_list); -internal LNK_SectionArray lnk_section_table_get_output_sections(Arena *arena, LNK_SectionTable *sectab); -internal LNK_Section * lnk_finalized_section_from_id(LNK_SectionTable *sectab, U64 id); - -internal LNK_SectionArray lnk_section_table_get_output_sections(Arena *arena, LNK_SectionTable *sectab); -internal void lnk_finalize_section_layout(LNK_SectionTable *sectab, LNK_Section *sect, U64 file_align); -internal void lnk_assign_section_index(LNK_Section *sect, U64 sect_idx); -internal void lnk_assign_section_virtual_space(LNK_Section *sect, U64 sect_align, U64 *voff_cursor); -internal void lnk_assign_section_file_space(LNK_Section *sect, U64 *foff_cursor);