diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 67f4626c..3e8d8131 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1221,8 +1221,8 @@ lnk_load_objs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer * // if machine type was unspecified on the command line, derive it from obj file if (config->machine == COFF_MachineType_Unknown) { for EachIndex(obj_idx, new_input_objs.count) { - if (new_objs[obj_idx].data.header.machine != COFF_MachineType_Unknown) { - config->machine = new_objs[obj_idx].data.header.machine; + if (new_objs[obj_idx].data.coff.header.machine != COFF_MachineType_Unknown) { + config->machine = new_objs[obj_idx].data.coff.header.machine; break; } } @@ -1335,7 +1335,6 @@ lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer lnk_obj_list_push_node(&link->objs, include_obj); } } - ProfEnd(); } @@ -2383,8 +2382,8 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer sect_filter |= COFF_SectionFlag_LnkRemove; // skip sections that are discarded from the output if ( ! lnk_do_debug_info(config)) { sect_filter |= LNK_SECTION_FLAG_DEBUG; } // on /DEBUG:NONE linker never invokes the debug info machinery - for EachIndex(sect_idx, obj->header.section_count_no_null) { - if (obj->section_flags[sect_idx] & sect_filter) { continue; } + for EachIndex(sect_idx, obj->coff.sections.count) { + if (obj->coff.sections.flags[sect_idx] & sect_filter) { continue; } // unpack section and relocations COFF_SectionHeader *section_header = §ion_table[sect_idx]; @@ -2524,7 +2523,7 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer // if (lnk_get_log_status(LNK_Log_InputObj)) { U64 total_input_size = 0; - for (LNK_ObjNode *obj_n = link->objs.first; obj_n != 0; obj_n = obj_n->next) { total_input_size += obj_n->data.data.size; } + for (LNK_ObjNode *obj_n = link->objs.first; obj_n != 0; obj_n = obj_n->next) { total_input_size += obj_n->data.coff.data.size; } lnk_log(LNK_Log_InputObj, "[Total Obj Input Size %M]", total_input_size); } if (lnk_get_log_status(LNK_Log_InputLib)) { @@ -2607,7 +2606,7 @@ lnk_obj_indices_from_section_counts(Arena *arena, U64 worker_count, LNK_Obj **ob } } - worker_section_counts[min_worker_idx] += objs[obj_idx]->header.section_count_no_null; + worker_section_counts[min_worker_idx] += objs[obj_idx]->coff.sections.count; worker_obj_counts[min_worker_idx] += 1; } @@ -2629,7 +2628,7 @@ lnk_obj_indices_from_section_counts(Arena *arena, U64 worker_count, LNK_Obj **ob U32Array *worker_obj_indices = &obj_indices[min_worker_idx]; worker_obj_indices->v[worker_obj_counts[min_worker_idx]++] = (U32)obj_idx; worker_obj_indices->count += 1; - worker_section_counts[min_worker_idx] += objs[obj_idx]->header.section_count_no_null; + worker_section_counts[min_worker_idx] += objs[obj_idx]->coff.sections.count; } scratch_end(scratch); @@ -2706,10 +2705,10 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task) for EachIndex(obj_idx, objs_count) { LNK_Obj *obj = objs[obj_idx]; - is_live[obj_idx] = push_array(scratch.arena, U8, obj->header.section_count_no_null + 1); + is_live[obj_idx] = push_array(scratch.arena, U8, obj->coff.sections.count + 1); - for EachIndex(sect_idx, obj->header.section_count_no_null) { - is_live[obj_idx][sect_idx + 1] = !(obj->section_flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT); + for EachIndex(sect_idx, obj->coff.sections.count) { + is_live[obj_idx][sect_idx + 1] = !(obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT); } } } @@ -2740,9 +2739,9 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task) for EachIndex(obj_idx, objs_count) { LNK_Obj *obj = objs[obj_idx]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { U32 section_number = sect_idx+1; - COFF_SectionFlags section_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx]; // is section eligible for walking? if (section_flags & COFF_SectionFlag_LnkRemove) { continue; } @@ -2807,7 +2806,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task) for EachNode(section_n, U32Node, associated_sections.first) { U32 section_number = section_n->data; - COFF_SectionFlags section_flags = ref_symbol.obj->section_flags[section_number-1]; + COFF_SectionFlags section_flags = ref_symbol.obj->coff.sections.flags[section_number-1]; // on first section visit, set live flag and enqueue section U8 was_visited = ins_atomic_u8_eval_assign(&is_live[ref_symbol.obj->input_idx][section_number], 1); @@ -2874,11 +2873,11 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task) for EachIndex(obj_idx, objs_count) { LNK_Obj *obj = objs[obj_idx]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { U32 section_number = sect_idx+1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); if ( ! is_live[obj->input_idx][section_number]) { - obj->section_flags[sect_idx] |= COFF_SectionFlag_LnkRemove; + obj->coff.sections.flags[sect_idx] |= COFF_SectionFlag_LnkRemove; } } } @@ -2891,24 +2890,24 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task) for EachIndex(obj_idx, objs_count) { LNK_Obj *obj = objs[obj_idx]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { U32 section_number = sect_idx+1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); U64 stat_kind = Stat_Null; - if (obj->section_flags[sect_idx] & LNK_SECTION_FLAG_DEBUG) { stat_kind = Stat_Debug; } - else if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntCode) { stat_kind = Stat_Code; } + if (obj->coff.sections.flags[sect_idx] & LNK_SECTION_FLAG_DEBUG) { stat_kind = Stat_Debug; } + else if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntCode) { stat_kind = Stat_Code; } else { stat_kind = Stat_Data; } if (is_live[obj->input_idx][section_number]) { stats[stat_kind].live_count += 1; - if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) { + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) { stats[stat_kind].live_vsize += section_header->vsize; } else { stats[stat_kind].live_fsize += section_header->fsize; } } else { - if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) { + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) { stats[stat_kind].vsize += section_header->vsize; } else { stats[stat_kind].fsize += section_header->fsize; @@ -2979,16 +2978,16 @@ lnk_icf_scope_from_section(LNK_Obj *obj, U32 sect_idx) // * section flags filter * COFF_SectionFlags expected_flags = COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_MemRead; COFF_SectionFlags exclude_flags = COFF_SectionFlag_LnkRemove | COFF_SectionFlag_MemWrite | LNK_SECTION_FLAG_NOICF; - if ((obj->section_flags[sect_idx] & expected_flags) != expected_flags || (obj->section_flags[sect_idx] & exclude_flags) != 0) { + if ((obj->coff.sections.flags[sect_idx] & expected_flags) != expected_flags || (obj->coff.sections.flags[sect_idx] & exclude_flags) != 0) { goto exit; } - if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntCode) { + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntCode) { result = LNK_ICF_Scope_Code; goto exit; } - if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntInitializedData) { + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntInitializedData) { U64 section_number = sect_idx + 1; COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number); String8 section_name = str8_cstring_capped(section_header->name, section_header->name + sizeof(section_header->name)); @@ -3043,7 +3042,7 @@ lnk_icf_scope_from_section(LNK_Obj *obj, U32 sect_idx) } exit:; - Assert(result == LNK_ICF_Scope_Null || obj->comdats[sect_idx] != max_U32); // TODO: are symlinks on COMDATs optional? + Assert(result == LNK_ICF_Scope_Null || obj->coff.sections.comdats[sect_idx] != max_U32); // TODO: are symlinks on COMDATs optional? return result; } @@ -3118,39 +3117,36 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) if (task->config->llvm_addrsig == LNK_SwitchState_Yes) { ProfBegin("Flag significant sections"); + // .llvm_addrsig is an array of ULEB128 symbol indices, which mark sections // whose addresses are significant for EachIndex(i, task->obj_indices[task_id].count) { U64 obj_idx = task->obj_indices[task_id].v[i]; LNK_Obj *obj = task->objs[obj_idx]; - if (obj->llvm_addrsig_sect_idx >= obj->header.section_count_no_null) { continue; } - - String8 symbol_table = lnk_coff_symbol_table_from_obj(obj); - String8 string_table = lnk_coff_string_table_from_obj(obj); - COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, obj->llvm_addrsig_sect_idx + 1); - String8 section_data = str8_substr(obj->data, r1u64s(section_header->foff, section_header->fsize)); + if (obj->coff.llvm_addrsig_sect_idx >= obj->coff.sections.count) { continue; } // parse symbol indices and mark selected sections with NOICF flag, // the selected symbols maybe undefined/weak which need to be resolved + String8 section_data = lnk_obj_section_data_from_sect_idx(obj, obj->coff.llvm_addrsig_sect_idx); for (U64 off = 0; off < section_data.size;) { U64 symbol_off = off; U64 symbol_idx = 0; off += str8_deserial_read_uleb128(section_data, off, &symbol_idx); if (symbol_off == off) { break; } - if (symbol_idx < obj->header.symbol_count) { + if (symbol_idx < obj->coff.header.symbol_count) { LNK_ObjSymbolRef target_ref = { .obj = obj, .symbol_idx = symbol_idx }; B32 is_symbol_found = lnk_resolve_reloc_target_symbol(scratch.arena, task->symtab, target_ref, str8_lit("/OPT:ICF"), &target_ref); if (is_symbol_found) { COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(target_ref.obj, target_ref.symbol_idx); if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular) { - target_ref.obj->section_flags[symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF; + target_ref.obj->coff.sections.flags[symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF; } } else { COFF_ParsedSymbol original_symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); if (coff_interp_from_parsed_symbol(original_symbol) == COFF_SymbolValueInterp_Regular) { - obj->section_flags[original_symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF; + obj->coff.sections.flags[original_symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF; } else { lnk_log(LNK_Log_Debug, "%S: .llvm_addrsig: contains an unresolved symbol index 0x%x at offset 0x%x", lnk_loc_from_obj(scratch.arena, obj), symbol_idx, symbol_off); } @@ -3179,7 +3175,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) for EachIndex(i, task->obj_indices[task_id].count) { U64 obj_idx = task->obj_indices[task_id].v[i]; LNK_Obj *obj = objs[obj_idx]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { if (lnk_icf_scope_from_section(obj, sect_idx)) { contrib_counts[obj_idx] += 1; } @@ -3209,13 +3205,13 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) U64 noncontrib_count = 0; for EachIndex(obj_idx, task->objs_count) { shared.noncontrib_offsets[obj_idx] = noncontrib_count; - noncontrib_count += objs[obj_idx]->header.section_count_no_null - contrib_counts[obj_idx]; + noncontrib_count += objs[obj_idx]->coff.sections.count - contrib_counts[obj_idx]; } shared.color_map = push_array(scratch.arena, U64 *, task->objs_count); for EachIndex(obj_idx, task->objs_count) { LNK_Obj *obj = objs[obj_idx]; - shared.color_map[obj_idx] = push_array(scratch.arena, U64, obj->header.section_count_no_null); + shared.color_map[obj_idx] = push_array(scratch.arena, U64, obj->coff.sections.count); } shared.contrib_offsets = offsets_from_counts_array_u64(scratch.arena, contrib_counts, task->objs_count); @@ -3240,7 +3236,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) LNK_Obj *obj = objs[obj_idx]; U64 cursor = 0; U64 noncontrib_cursor = 0; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { LNK_ICF_Scope scope = lnk_icf_scope_from_section(obj, sect_idx); if (scope == LNK_ICF_Scope_Null) { // assign colors in object order to avoid a contended atomic allocator @@ -3278,7 +3274,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) U64 reloc_cursor = 0; for EachNode(associated_n, U32Node, associated_sections.first) { COFF_SectionHeader *associated_header = lnk_coff_section_header_from_section_number(obj, associated_n->data); - String8 associated_data = str8_substr(obj->data, r1u64s(associated_header->foff, associated_header->fsize)); + String8 associated_data = lnk_obj_section_data_from_sect_idx(obj, associated_n->data - 1); COFF_RelocArray associated_relocs = lnk_coff_relocs_from_section_header(obj, associated_header); lnk_hasher_update_string(&hasher, associated_data); @@ -3306,12 +3302,12 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) U32 target_sect = target_symbol.section_number; // use the selected COMDAT leader so equivalent targets hash alike - if (target_sect != 0 && target_sect <= target_obj->header.section_count_no_null && - target_obj->section_flags[target_sect - 1] & COFF_SectionFlag_LnkCOMDAT) { + if (target_sect != 0 && target_sect <= target_obj->coff.sections.count && + target_obj->coff.sections.flags[target_sect - 1] & COFF_SectionFlag_LnkCOMDAT) { LNK_ObjSymbolRef leader_ref = {0}; if (lnk_obj_get_comdat_symlink(target_obj, target_sect, &leader_ref)) { COFF_ParsedSymbol leader_symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(leader_ref.obj, leader_ref.symbol_idx); - if (leader_symbol.section_number != 0 && leader_symbol.section_number <= leader_ref.obj->header.section_count_no_null) { + if (leader_symbol.section_number != 0 && leader_symbol.section_number <= leader_ref.obj->coff.sections.count) { target_obj = leader_ref.obj; target_sect = leader_symbol.section_number; } @@ -3606,8 +3602,8 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) // TODO: double-check if discarded section headers should be updated with leaders' alignment, // leaders at this point are resolved - U64 contrib_align = coff_align_size_from_section_flags(contrib_obj->section_flags[contrib->sect_idx]); - COFF_SectionFlags *leader_flags = &leader_obj->section_flags[leader->sect_idx]; + U64 contrib_align = coff_align_size_from_section_flags(contrib_obj->coff.sections.flags[contrib->sect_idx]); + COFF_SectionFlags *leader_flags = &leader_obj->coff.sections.flags[leader->sect_idx]; for (COFF_SectionFlags old_flags = ins_atomic_u32_eval((U32 *)leader_flags);;) { U64 leader_align = coff_align_size_from_section_flags(old_flags); if (leader_align >= contrib_align) { break; } @@ -3622,10 +3618,10 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) } // remove folded section from the image - contrib_obj->section_flags[contrib->sect_idx] |= COFF_SectionFlag_LnkRemove; + contrib_obj->coff.sections.flags[contrib->sect_idx] |= COFF_SectionFlag_LnkRemove; // update folded section COMDAT symlink to point to the leader section - contrib_obj->symlinks[contrib->sect_idx + 1] = (LNK_ObjSymbolRef){ leader_obj, leader_obj->comdats[leader->sect_idx] }; + contrib_obj->symlinks[contrib->sect_idx + 1] = (LNK_ObjSymbolRef){ leader_obj, leader_obj->coff.sections.comdats[leader->sect_idx] }; #if LNK_PARANOID String8 section_name = lnk_obj_section_name_from_section_number(contrib_obj, contrib->sect_idx+1); @@ -3691,7 +3687,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task) for EachIndex(i, task->obj_indices[task_id].count) { U64 obj_idx = task->obj_indices[task_id].v[i]; LNK_Obj *obj = objs[obj_idx]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { U64 section_number = sect_idx + 1; LNK_ObjSymbolRef symlink_ref = {0}; @@ -3758,7 +3754,7 @@ lnk_section_definition_is_before(void *raw_a, void *raw_b) internal B32 lnk_should_gather_section(LNK_Obj *obj, U64 sect_idx, COFF_SectionHeader *sect_header) { - COFF_SectionFlags sect_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx]; // removed sections were eliminated before image layout if (sect_flags & COFF_SectionFlag_LnkRemove) { @@ -3801,10 +3797,10 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) ProfBegin("Gather Section Definitions"); for EachInRange(obj_idx, range) { LNK_Obj *obj = task->objs[obj_idx]; - COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; - String8 string_table = str8_substr(obj->data, obj->header.string_table_range); + COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->coff.data, obj->coff.header.section_table_range).str; + String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range); - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; if ( ! lnk_should_gather_section(obj, sect_idx, sect_header)) { continue; } @@ -3812,7 +3808,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) Temp temp = temp_begin(scratch.arena); // was section defined? - COFF_SectionFlags image_sect_flags = obj->section_flags[sect_idx] & ~(COFF_SectionFlags_LnkFlags | COFF_SectionFlags_Reserved); + COFF_SectionFlags image_sect_flags = obj->coff.sections.flags[sect_idx] & ~(COFF_SectionFlags_LnkFlags | COFF_SectionFlags_Reserved); String8 sect_name = coff_name_from_section_header(string_table, sect_header); image_sect_flags = lnk_apply_section_directives_to_flags(task->config, sect_name, image_sect_flags); String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, image_sect_flags); @@ -3893,7 +3889,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) LNK_Obj *obj = sect_defn->obj; U32 sect_number = sect_defn->obj_sect_idx + 1; COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, sect_number); - String8 sect_name = coff_name_from_section_header(str8_substr(obj->data, obj->header.string_table_range), sect_header); + String8 sect_name = coff_name_from_section_header(str8_substr(obj->coff.data, obj->coff.header.string_table_range), sect_header); String8 expected_flags_str = coff_string_from_section_flags(main_arena, sect_n->data.flags); String8 current_flags_str = coff_string_from_section_flags(main_arena, sect_defn->flags); lnk_error_obj(LNK_Warning_SectionFlagsConflict, sect_defn->obj, "detected section flags conflict in %S(No. %X); expected {%S} but got {%S}", sect_name, sect_number, expected_flags_str, current_flags_str); @@ -3922,7 +3918,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) ProfBegin("Alloc Section Map"); task->sect_map = push_array(main_arena, LNK_SectionContrib **, task->objs_count); - for EachIndex(obj_idx, task->objs_count) { task->sect_map[obj_idx] = push_array(main_arena, LNK_SectionContrib *, task->objs[obj_idx]->header.section_count_no_null); } + for EachIndex(obj_idx, task->objs_count) { task->sect_map[obj_idx] = push_array(main_arena, LNK_SectionContrib *, task->objs[obj_idx]->coff.sections.count); } ProfEnd(); } @@ -3931,14 +3927,14 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) ProfBegin("Gather Section Contribs"); for EachInRange(obj_idx, range) { LNK_Obj *obj = task->objs[obj_idx]; - COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str; - String8 string_table = str8_substr(obj->data, obj->header.string_table_range); + COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->coff.data, obj->coff.header.section_table_range).str; + String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range); ProfBeginV("Gather Section Contribs [%S]", obj->path); - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { LNK_SectionContrib *sc = task->null_sc; COFF_SectionHeader *sect_header = §ion_table[sect_idx]; - COFF_SectionFlags sect_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx]; task->sect_map[obj_idx][sect_idx] = sc; if ( ! lnk_should_gather_section(obj, sect_idx, sect_header)) { continue; } @@ -3959,7 +3955,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task) if (sect_flags & COFF_SectionFlag_CntUninitializedData) { data = str8(0, sect_header->fsize); } else { - data = str8_substr(obj->data, rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize)); + data = lnk_obj_section_data_from_sect_idx(obj, sect_idx); } U16 sc_align = coff_align_size_from_section_flags(sect_flags); @@ -3988,10 +3984,10 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task) LNK_Obj *obj = task->objs[obj_idx]; ProfBeginV("Set COMDAT Section Contribs [%S]", obj->path); - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { U64 section_number = sect_idx+1; - if (~obj->section_flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT) { continue; } + if (~obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT) { continue; } LNK_ObjSymbolRef symlink_ref = {0}; if ( ! lnk_obj_get_comdat_symlink(obj, section_number, &symlink_ref)) { continue; } @@ -4010,11 +4006,11 @@ THREAD_POOL_TASK_FUNC(lnk_flag_debug_symbols_task) LNK_Obj *obj = task->objs[obj_idx]; COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { - if (obj->section_flags[symbol.section_number-1] & LNK_SECTION_FLAG_DEBUG) { + if (obj->coff.sections.flags[symbol.section_number-1] & LNK_SECTION_FLAG_DEBUG) { task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1; } } @@ -4030,7 +4026,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task) ProfBeginV("Patch COMDAT Offsets in %S", obj->path); COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); @@ -4050,7 +4046,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task) B32 should_patch = 0; if (is_same_obj) { - B32 is_static_comdat_leader = symbol.storage_class == COFF_SymStorageClass_Static && obj->comdats[symbol.section_number-1] == symbol_idx; + B32 is_static_comdat_leader = symbol.storage_class == COFF_SymStorageClass_Static && obj->coff.sections.comdats[symbol.section_number-1] == symbol_idx; if (is_external || is_static_comdat_leader) { section_number = leader_symbol.section_number; value = leader_symbol.value; @@ -4256,7 +4252,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_common_block_symbols_task) ProfBeginV("Patch Common Block Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Common) { @@ -4283,7 +4279,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task) ProfBeginV("Patch Regular Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); if (task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx]) { continue; } @@ -4315,7 +4311,7 @@ lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Obj *obj, B8 *was_symbol_patch ProfBeginV("%S\n", obj->path); COFF_ParsedSymbol fixup_dst; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + fixup_dst.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + fixup_dst.aux_symbol_count)) { fixup_dst = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); if (was_symbol_patched[symbol_idx]) { continue; } @@ -4422,7 +4418,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher) LNK_ObjRelocPatcher *task = raw_task; LNK_Obj *obj = task->objs[task_id]; - COFF_FileHeaderInfo obj_header = obj->header; + COFF_FileHeaderInfo obj_header = obj->coff.header; COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); String8 symbol_table = lnk_coff_symbol_table_from_obj(obj); String8 string_table = lnk_coff_string_table_from_obj(obj); @@ -4433,16 +4429,15 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher) for EachIndex(sect_idx, obj_header.section_count_no_null) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; - COFF_SectionFlags section_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx]; if (section_flags & COFF_SectionFlag_LnkInfo) { continue; } if (section_flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_flags & COFF_SectionFlag_CntUninitializedData) { continue; } // get section bytes (special case debug info because it is not copied to the image) - String8 data = section_flags & LNK_SECTION_FLAG_DEBUG ? obj->data : task->image_data; Rng1U64 section_frange = rng_1u64(section_header->foff, section_header->foff + section_header->fsize); - String8 section_data = str8_substr(data, section_frange); + String8 section_data = section_flags & LNK_SECTION_FLAG_DEBUG ? lnk_obj_section_data_from_sect_idx(obj, sect_idx) : str8_substr(task->image_data, section_frange); // apply relocs COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section_header); @@ -4450,12 +4445,12 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher) COFF_Reloc *reloc = &relocs.v[reloc_idx]; // error check relocation - if (obj->header.machine == COFF_MachineType_X64) { + if (obj->coff.header.machine == COFF_MachineType_X64) { if (reloc->type > COFF_Reloc_X64_Last) { lnk_error_obj(LNK_Error_IllegalRelocation, obj, "unknown relocation type 0x%x", reloc->type); } - } else if (obj->header.machine != COFF_MachineType_Unknown) { - lnk_not_implemented("relocation patching is not implemented for %S", coff_string_from_machine_type(obj->header.machine)); + } else if (obj->coff.header.machine != COFF_MachineType_Unknown) { + lnk_not_implemented("relocation patching is not implemented for %S", coff_string_from_machine_type(obj->coff.header.machine)); continue; } @@ -4571,15 +4566,15 @@ THREAD_POOL_TASK_FUNC(lnk_flag_hotpatch_contribs_task) U64 obj_idx = task_id; LNK_Obj *obj = task->objs[obj_idx]; - if (obj->hotpatch) { + if (obj->coff.hotpatch) { COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) { LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1]; if (sc != task->null_sc) { - sc->hotpatch = !!(obj->section_flags[symbol.section_number-1] & COFF_SectionFlag_CntCode); + sc->hotpatch = !!(obj->coff.sections.flags[symbol.section_number-1] & COFF_SectionFlag_CntCode); } } } @@ -4941,9 +4936,9 @@ THREAD_POOL_TASK_FUNC(lnk_patch_virtual_offsets_and_sizes_in_obj_section_headers ProfBeginV("Patch Virtual Offset And Size In Section Headers [%S]", obj->path); COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { + for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; - if (~obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) { + if (~obj->coff.sections.flags[sect_idx] & 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_contrib(sc); @@ -4962,9 +4957,9 @@ THREAD_POOL_TASK_FUNC(lnk_patch_file_offsets_and_sizes_in_obj_section_headers_ta ProfBeginV("Patch File Offsets And Sizes In Obj Section Headers [%S]", obj->path); COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { + for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) { COFF_SectionHeader *sect_header = §ion_table[sect_idx]; - COFF_SectionFlags sect_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx]; B32 patch_section_header = (~sect_flags & COFF_SectionFlag_LnkRemove) && (~sect_flags & LNK_SECTION_FLAG_DEBUG); if (patch_section_header) { @@ -4988,16 +4983,16 @@ THREAD_POOL_TASK_FUNC(lnk_patch_section_symbols_task) ProfBegin("Patch Section Symbols [%S]", obj->path); COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Undefined) { if (symbol.storage_class == COFF_SymStorageClass_Section) { B32 is_referenced = 0; COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj); - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; - COFF_SectionFlags section_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx]; if (section_flags & COFF_SectionFlag_LnkRemove) { continue; } if (section_flags & COFF_SectionFlag_LnkInfo) { continue; } if (section_flags & LNK_SECTION_FLAG_DEBUG) { continue; } @@ -5061,9 +5056,9 @@ THREAD_POOL_TASK_FUNC(lnk_gather_base_reloc_pages_task) COFF_SectionHeader *sect_table = lnk_coff_section_table_from_obj(obj); ProfBeginV("%S", obj->path); - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { COFF_SectionHeader *sect_header = §_table[sect_idx]; - if (obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; } + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; } COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, sect_header); for EachIndex(reloc_idx, relocs.count) { @@ -5073,7 +5068,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_base_reloc_pages_task) COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol); if (symbol_interp == COFF_SymbolValueInterp_Abs) { continue; } - U64 is_addr = coff_is_addr_reloc(obj->header.machine, r->type); + U64 is_addr = coff_is_addr_reloc(obj->coff.header.machine, r->type); if (is_addr == 0) { continue; } U64 reloc_voff = sect_header->voff + r->apply_off; @@ -5759,7 +5754,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT task.u.patch_symtabs.common_block_ranges = tp_divide_work(temp.arena, common_block_contribs_count, tp->worker_count); task.u.patch_symtabs.common_block_contribs = common_block_contribs; task.u.patch_symtabs.was_symbol_patched = push_array(temp.arena, B8 *, objs_count); - for EachIndex(obj_idx, objs_count) { task.u.patch_symtabs.was_symbol_patched[obj_idx] = push_array(temp.arena, B8, objs[obj_idx]->header.symbol_count); } + for EachIndex(obj_idx, objs_count) { task.u.patch_symtabs.was_symbol_patched[obj_idx] = push_array(temp.arena, B8, objs[obj_idx]->coff.header.symbol_count); } // flag debug symbols to prevent them from being patched in subsequent passes tp_for_parallel_prof(tp, 0, objs_count, lnk_flag_debug_symbols_task, &task, "Flag Debug Symbols"); @@ -6139,15 +6134,15 @@ lnk_obj_sect_idx_from_section(Arena *arena, U64 objs_count, LNK_Obj **objs, LNK_ PairU32 *obj_sect_idxs = push_array(arena, PairU32, max_contribs); for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) { LNK_Obj *obj = objs[obj_idx]; - COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); - String8 string_table = str8_substr(obj->data, obj->header.string_table_range); - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { + COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0); + String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range); + for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; String8 full_section_name = coff_name_from_section_header(string_table, section_header); String8 section_name, section_postfix; coff_parse_section_name(full_section_name, §ion_name, §ion_postfix); - if (obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; } + if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; } if (section_header->fsize == 0) { continue; } if (lnk_is_section_removed(config, section_name)) { continue; } @@ -6172,7 +6167,7 @@ internal COFF_SectionHeader * lnk_coff_section_header_from_obj_sect_idx_pair(LNK_Obj **objs, PairU32 p) { LNK_Obj *obj = objs[p.v0]; - COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); + COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0); return §ion_table[p.v1]; } @@ -6287,7 +6282,7 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs String8List source_list = {0}; if (obj) { COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1); - String8 string_table = str8_substr(obj->data, obj->header.string_table_range); + String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range); String8 section_name = coff_name_from_section_header(string_table, section_header); LNK_Lib *lib = lnk_obj_get_lib(obj); if (lib) { @@ -6315,10 +6310,10 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs str8_list_pushf(arena, &map, "# DEBUG\n"); for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) { LNK_Obj *obj = objs[obj_idx]; - COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0); - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { + COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0); + for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; - COFF_SectionFlags section_flags = obj->section_flags[sect_idx]; + COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx]; if (~section_flags & COFF_SectionFlag_LnkRemove && section_flags & LNK_SECTION_FLAG_DEBUG) { LNK_Lib *lib = lnk_obj_get_lib(obj); if (lib) { @@ -6812,12 +6807,11 @@ lnk_run_type_server(TP_Context *tp, TP_Arena *arena, LNK_Config *config) if (obj->link_member) { continue; } // does obj have debug types? - if (obj->debug_p_sect_idx < obj->header.section_count_no_null) { + if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) { u64_list_push(scratch.arena, &include_obj_list, obj_idx); - } else if (obj->debug_t_sect_idx < obj->header.section_count_no_null) { + } else if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) { // read first leaf - LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx); - String8 raw_debug_t = str8_substr(obj->data, section.frange); + String8 raw_debug_t = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx); CV_Leaf leaf = {0}; cv_read_leaf(raw_debug_t, 0, 1, &leaf); diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 213c8f76..c8efd6e0 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -76,10 +76,8 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_h_task) LNK_CodeViewInput *task = raw_task; LNK_Obj *obj = task->obj_arr[obj_idx]; - if (obj->debug_h_sect_idx < obj->header.section_count_no_null) { - LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_h_sect_idx); - - String8 raw_debug_h = str8_substr(obj->data, section.frange); + if (obj->coff.debug_h_sect_idx < obj->coff.sections.count) { + String8 raw_debug_h = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_h_sect_idx); CV_DebugH *debug_h = &task->debug_h_arr[obj_idx]; LLVM_GHash ghash = {0}; U64 ghash_read_size = str8_deserial_read_struct(raw_debug_h, 0, &ghash); @@ -599,6 +597,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o } // unpack type data + type_data_raw = push_str8_copy(arena, type_data_raw); String8 type_data[CV_TypeIndexSource_COUNT] = {0}; for EachIndex(ti_source, CV_TypeIndexSource_COUNT) { type_data[ti_source] = str8_substr(type_data_raw, type_data_ranges[ti_source]); @@ -700,9 +699,9 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, if (rrt->obj_time_stamps[rrt_obj_idx] != obj_file_props.modified) { continue; } // invalidate debug section pointers - obj->debug_t_sect_idx = ~0; - obj->debug_p_sect_idx = ~0; - obj->debug_h_sect_idx = ~0; + obj->coff.debug_t_sect_idx = ~0; + obj->coff.debug_p_sect_idx = ~0; + obj->coff.debug_h_sect_idx = ~0; // apply type index map obj->ti_range = rrt->obj_ti_ranges[rrt_obj_idx]; @@ -734,15 +733,15 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, for EachNode(n, String8Node, input.debug_s_list_arr[obj_idx].first) { total_debug_s_size += n->string.size; } - if (obj->debug_t_sect_idx < obj->header.section_count_no_null) { - total_debug_t_size += lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx).header->fsize; + if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) { + total_debug_t_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_t_sect_idx).header->fsize; } - if (obj->debug_p_sect_idx < obj->header.section_count_no_null) { - total_debug_p_size += lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx).header->fsize; + if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) { + total_debug_p_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_p_sect_idx).header->fsize; } if (config->ghash) { - if (obj->debug_h_sect_idx < obj->header.section_count_no_null) { - total_debug_h_size += lnk_obj_section_from_sect_idx(obj, obj->debug_h_sect_idx).header->fsize; + if (obj->coff.debug_h_sect_idx < obj->coff.sections.count) { + total_debug_h_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_h_sect_idx).header->fsize; } } } @@ -784,18 +783,16 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, for EachIndex(obj_idx, obj_count) { LNK_Obj *obj = obj_arr[obj_idx]; - if (obj->debug_t_sect_idx < obj->header.section_count_no_null) { - LNK_ObjSection debug_t_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx); + if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) { raw_debug_t_arr[obj_idx].count = 1; raw_debug_t_arr[obj_idx].v = push_array(scratch.arena, String8, 1); - raw_debug_t_arr[obj_idx].v[0] = str8_substr(obj->data, debug_t_sect.frange); + raw_debug_t_arr[obj_idx].v[0] = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx); } - if (obj->debug_p_sect_idx < obj->header.section_count_no_null) { - LNK_ObjSection debug_p_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx); + if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) { raw_debug_p_arr[obj_idx].count = 1; raw_debug_p_arr[obj_idx].v = push_array(scratch.arena, String8, 1); - raw_debug_p_arr[obj_idx].v[0] = str8_substr(obj->data, debug_p_sect.frange); + raw_debug_p_arr[obj_idx].v[0] = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_p_sect_idx); } } @@ -2852,13 +2849,13 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task) LNK_Obj *obj = task->cv->obj_arr[obj_idx]; PDB_DbiSCArray *sc_array = &task->sc_arrays[obj_idx]; - sc_array->v = push_array_no_zero(arena, PDB_DbiSC, obj->header.section_count_no_null); - sc_array->cap = obj->header.section_count_no_null; + sc_array->v = push_array_no_zero(arena, PDB_DbiSC, obj->coff.sections.count); + sc_array->cap = obj->coff.sections.count; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { // filter by section flags - if (obj->section_flags[sect_idx] & (COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkRemove | LNK_SECTION_FLAG_DEBUG)) { continue; } + if (obj->coff.sections.flags[sect_idx] & (COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkRemove | LNK_SECTION_FLAG_DEBUG)) { continue; } // skip unwind info for the section contribution String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx); diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index 1259157d..b2074265 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -156,6 +156,13 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) } } + String8 *section_data = push_array(arena, String8, header.section_count_no_null); + for EachIndex(sect_idx, header.section_count_no_null) { + COFF_SectionHeader *sect_header = &coff_section_table[sect_idx]; + String8 data = str8_substr(input->data, r1u64s(sect_header->foff, sect_header->fsize)); + section_data[sect_idx] = section_flags[sect_idx] & LNK_SECTION_FLAG_DEBUG ? push_str8_copy(arena, data) : data; + } + // // error check symbol table and cache name lengths for primary symbols // @@ -168,38 +175,46 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) } } - U64 symbol_block_count = CeilIntegerDiv(header.symbol_count, 64); + U64 symbol_block_count = CeilIntegerDiv(header.symbol_count, 64); LNK_ObjSymbolArray symbols = { .count = primary_symbol_count, .primary_masks = push_array(arena, U64, symbol_block_count), - .block_bases = push_array_no_zero(arena, U32, symbol_block_count), - .values = push_array_no_zero(arena, U64, primary_symbol_count), - .section_numbers = push_array_no_zero(arena, U32, primary_symbol_count), - .types = push_array_no_zero(arena, COFF_SymbolType, primary_symbol_count), + .block_bases = push_array_no_zero(arena, U32, symbol_block_count), + .values = push_array_no_zero(arena, U64, primary_symbol_count), + .section_numbers = push_array_no_zero(arena, U32, primary_symbol_count), + .types = push_array_no_zero(arena, COFF_SymbolType, primary_symbol_count), .storage_classes = push_array_no_zero(arena, COFF_SymStorageClass, primary_symbol_count), - .aux_counts = push_array_no_zero(arena, U8, primary_symbol_count), - .name_offsets = push_array_no_zero(arena, U32, primary_symbol_count), - .name_sizes = push_array_no_zero(arena, U32, primary_symbol_count), + .aux_counts = push_array_no_zero(arena, U8, primary_symbol_count), + .name_offsets = push_array_no_zero(arena, U32, primary_symbol_count), + .name_sizes = push_array_no_zero(arena, U32, primary_symbol_count), }; { - U64 next_block = 0; + U64 next_block = 0; U32 primary_idx = 0; COFF_ParsedSymbol symbol; for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx); - U64 block_idx = symbol_idx >> 6; - while (next_block <= block_idx) { - symbols.block_bases[next_block++] = primary_idx; + + // copy out primary symbols + { + U64 block_idx = symbol_idx >> 6; + while (next_block <= block_idx) { + symbols.block_bases[next_block++] = primary_idx; + } + + symbols.primary_masks[block_idx] |= 1ull << (symbol_idx & 63); + + symbols.values [primary_idx] = symbol.value; + symbols.section_numbers[primary_idx] = symbol.section_number; + symbols.types [primary_idx] = symbol.type; + symbols.storage_classes[primary_idx] = symbol.storage_class; + symbols.aux_counts [primary_idx] = symbol.aux_symbol_count; + symbols.name_offsets [primary_idx] = symbol.name.size ? safe_cast_u32(symbol.name.str - input->data.str) : 0; + symbols.name_sizes [primary_idx] = safe_cast_u32(symbol.name.size); + primary_idx += 1; } - symbols.primary_masks[block_idx] |= 1ull << (symbol_idx & 63); - symbols.values[primary_idx] = symbol.value; - symbols.section_numbers[primary_idx] = symbol.section_number; - symbols.types[primary_idx] = symbol.type; - symbols.storage_classes[primary_idx] = symbol.storage_class; - symbols.aux_counts[primary_idx] = symbol.aux_symbol_count; - symbols.name_offsets[primary_idx] = symbol.name.size ? safe_cast_u32(symbol.name.str - input->data.str) : 0; - symbols.name_sizes[primary_idx] = safe_cast_u32(symbol.name.size); - primary_idx += 1; + COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); if (interp == COFF_SymbolValueInterp_Regular) { if (symbol.section_number == 0 || symbol.section_number > header.section_count_no_null) { @@ -381,22 +396,28 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) } // fill out obj - obj->data = input->data; + obj->coff = (LNK_ObjCoff){ + .data = input->data, + .header = header, + .sections = { + .count = header.section_count_no_null, + .headers = section_headers, + .flags = section_flags, + .data = section_data, + .comdats = comdats, + .associations = associated_sections, + }, + .symbols = symbols, + .debug_t_sect_idx = debug_t_sect_idx, + .debug_p_sect_idx = debug_p_sect_idx, + .debug_h_sect_idx = debug_h_sect_idx, + .llvm_addrsig_sect_idx = llvm_addrsig_sect_idx, + .hotpatch = hotpatch, + }; obj->path = push_str8_copy(arena, input->path); - obj->header = header; - obj->section_headers = section_headers; - obj->section_flags = section_flags; - obj->symbols = symbols; - obj->comdats = comdats; obj->exclude_from_debug_info = input->exclude_from_debug_info; - obj->hotpatch = hotpatch; - obj->associated_sections = associated_sections; obj->self = &task->objs[task_id]; obj->link_member = input->link_member; - obj->debug_t_sect_idx = debug_t_sect_idx; - obj->debug_p_sect_idx = debug_p_sect_idx; - obj->debug_h_sect_idx = debug_h_sect_idx; - obj->llvm_addrsig_sect_idx = llvm_addrsig_sect_idx; } internal LNK_ObjNode * @@ -447,7 +468,7 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table) LNK_InputCoffSymbolTable *task = raw_task; LNK_Obj *obj = task->objs[task_id]; COFF_ParsedSymbol symbol = {0}; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); LNK_SymbolSearchType search_type = lnk_symbol_search_type_from_coff(obj, symbol, interp); @@ -493,14 +514,14 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table) internal LNK_ObjSymbolRef * lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj) { - LNK_ObjSymbolRef *symlinks = push_array(arena, LNK_ObjSymbolRef, obj->header.section_count_no_null + 1); + LNK_ObjSymbolRef *symlinks = push_array(arena, LNK_ObjSymbolRef, obj->coff.sections.count + 1); COFF_ParsedSymbol symbol = {0}; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol); if (interp != COFF_SymbolValueInterp_Regular) { continue; } - COFF_SectionFlags section_flags = obj->section_flags[symbol.section_number - 1]; + COFF_SectionFlags section_flags = obj->coff.sections.flags[symbol.section_number - 1]; if (~section_flags & COFF_SectionFlag_LnkCOMDAT) { continue; } LNK_ObjSymbolRef *symlink = &symlinks[symbol.section_number]; @@ -556,12 +577,12 @@ lnk_obj_collect_associated_sections(Arena *arena, LNK_Obj *obj, U32 root_section // walk the complete descendant chain because associated COMDATs can nest for EachNode(parent_n, U32Node, queue.first) { - for EachNode(associated_n, U32Node, obj->associated_sections[parent_n->data]) { + for EachNode(associated_n, U32Node, obj->coff.sections.associations[parent_n->data]) { U32 child_section = associated_n->data; if (child_section == 0) { continue; } if (hash_map_search_u64_u64(&seen_hm, child_section)) { continue; } - if (obj->section_flags[child_section - 1] & skip_flags) { continue; } + if (obj->coff.sections.flags[child_section - 1] & skip_flags) { continue; } hash_map_push_u64_u64(scratch.arena, &seen_hm, child_section, 1); u32_list_push(arena, &queue, child_section); @@ -610,7 +631,7 @@ internal COFF_ParsedSymbol lnk_obj_match_symbol(LNK_Obj *obj, String8 match_name) { COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); if (str8_match(symbol.name, match_name, 0)) { return symbol; @@ -657,7 +678,7 @@ lnk_obj_get_lib_path(LNK_Obj *obj) internal U32 lnk_obj_get_removed_section_number(LNK_Obj *obj) { - return obj->header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16; + return obj->coff.header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16; } internal B32 @@ -674,20 +695,42 @@ lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number, LNK_ObjSymbolRef *s internal COFF_SectionHeader * lnk_coff_section_table_from_obj(LNK_Obj *obj) { - return obj->section_headers; + return obj->coff.sections.headers; +} + +internal String8 +lnk_obj_section_data_from_sect_idx(LNK_Obj *obj, U64 sect_idx) +{ + Assert(sect_idx < obj->coff.sections.count); + return obj->coff.sections.data[sect_idx]; +} + +internal U64 +lnk_obj_foff_from_section_data_ptr(LNK_Obj *obj, void *ptr) +{ + U64 ptr_v = IntFromPtr(ptr); + for EachIndex(sect_idx, obj->coff.sections.count) { + String8 data = obj->coff.sections.data[sect_idx]; + U64 data_min = IntFromPtr(data.str); + if (data_min <= ptr_v && ptr_v < data_min + data.size) { + return obj->coff.sections.headers[sect_idx].foff + ptr_v - data_min; + } + } + InvalidPath; + return 0; } internal U64 lnk_obj_sect_idx_from_section_number(LNK_Obj *obj, U64 section_number) { - Assert(1 <= section_number && section_number <= obj->header.section_count_no_null); + Assert(1 <= section_number && section_number <= obj->coff.sections.count); return section_number-1; } internal U64 lnk_obj_section_number_from_sect_idx(LNK_Obj *obj, U64 sect_idx) { - Assert(sect_idx < obj->header.section_count_no_null); + Assert(sect_idx < obj->coff.sections.count); return sect_idx+1; } @@ -708,13 +751,13 @@ lnk_obj_section_name_from_section_number(LNK_Obj *obj, U64 section_number) internal LNK_ObjSection lnk_obj_section_from_sect_idx(LNK_Obj *obj, U64 sect_idx) { - Assert(sect_idx < obj->header.section_count_no_null); + Assert(sect_idx < obj->coff.sections.count); LNK_ObjSection section = {0}; section.obj = obj; section.sect_idx = sect_idx; section.section_number = sect_idx+1; section.header = &lnk_coff_section_table_from_obj(obj)[sect_idx]; - section.flags = &obj->section_flags[sect_idx]; + section.flags = &obj->coff.sections.flags[sect_idx]; section.vrange = rng_1u64(section.header->voff, section.header->voff + section.header->vsize); section.frange = rng_1u64(section.header->foff, section.header->foff + section.header->fsize); section.reloc_count = section.header->reloc_count; @@ -731,8 +774,8 @@ lnk_obj_section_from_section_number(LNK_Obj *obj, U64 section_number) internal COFF_RelocArray lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_header) { - COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section_header); - COFF_Reloc *relocs = (COFF_Reloc *)(obj->data.str + reloc_info.array_off); + COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->coff.data, section_header); + COFF_Reloc *relocs = (COFF_Reloc *)(obj->coff.data.str + reloc_info.array_off); COFF_RelocArray result = { .count = reloc_info.count, .v = relocs }; return result; } @@ -740,21 +783,21 @@ lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_he internal String8 lnk_coff_string_table_from_obj(LNK_Obj *obj) { - return str8_substr(obj->data, obj->header.string_table_range); + return str8_substr(obj->coff.data, obj->coff.header.string_table_range); } internal String8 lnk_coff_symbol_table_from_obj(LNK_Obj *obj) { - return str8_substr(obj->data, obj->header.symbol_table_range); + return str8_substr(obj->coff.data, obj->coff.header.symbol_table_range); } internal COFF_RelocArray lnk_coff_reloc_info_from_section_number(LNK_Obj *obj, U64 section_number) { LNK_ObjSection section = lnk_obj_section_from_section_number(obj, section_number); - COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section.header); - COFF_Reloc *relocs = str8_deserial_get_raw_ptr(obj->data, reloc_info.array_off, sizeof(*relocs)*reloc_info.count); + COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->coff.data, section.header); + COFF_Reloc *relocs = str8_deserial_get_raw_ptr(obj->coff.data, reloc_info.array_off, sizeof(*relocs)*reloc_info.count); COFF_RelocArray result = { .count = reloc_info.count, .v = relocs }; return result; } @@ -763,10 +806,10 @@ internal B32 lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out) { Assert(section_number > 0); - U32 symbol_idx = obj->comdats[section_number-1]; + U32 symbol_idx = obj->coff.sections.comdats[section_number-1]; if (symbol_idx != max_U32) { COFF_ParsedSymbol secdef = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); - coff_parse_secdef(secdef, obj->header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out); + coff_parse_secdef(secdef, obj->coff.header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out); return 1; } return 0; @@ -777,7 +820,7 @@ lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number) { Assert(section_number > 0); U64 sect_idx = section_number - 1; - return &obj->section_headers[sect_idx]; + return &obj->coff.sections.headers[sect_idx]; } internal force_inline U64 @@ -785,22 +828,22 @@ lnk_obj_primary_symbol_idx_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx) { U64 block_idx = symbol_idx >> 6; U64 bit = 1ull << (symbol_idx & 63); - U64 block_mask = obj->symbols.primary_masks[block_idx]; + U64 block_mask = obj->coff.symbols.primary_masks[block_idx]; Assert(block_mask & bit); - return obj->symbols.block_bases[block_idx] + count_bits_set64(block_mask & (bit - 1)); + return obj->coff.symbols.block_bases[block_idx] + count_bits_set64(block_mask & (bit - 1)); } internal force_inline COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx_no_name(LNK_Obj *obj, U64 symbol_idx) { U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx); - U64 symbol_size = obj->header.is_big_obj ? sizeof(COFF_Symbol32) : sizeof(COFF_Symbol16); + U64 symbol_size = obj->coff.header.is_big_obj ? sizeof(COFF_Symbol32) : sizeof(COFF_Symbol16); COFF_ParsedSymbol result = { - .value = obj->symbols.values[primary_idx], - .section_number = obj->symbols.section_numbers[primary_idx], - .type = obj->symbols.types[primary_idx], - .storage_class = obj->symbols.storage_classes[primary_idx], - .aux_symbol_count = obj->symbols.aux_counts[primary_idx], + .value = obj->coff.symbols.values[primary_idx], + .section_number = obj->coff.symbols.section_numbers[primary_idx], + .type = obj->coff.symbols.types[primary_idx], + .storage_class = obj->coff.symbols.storage_classes[primary_idx], + .aux_symbol_count = obj->coff.symbols.aux_counts[primary_idx], .raw_symbol = lnk_coff_symbol_table_from_obj(obj).str + symbol_idx * symbol_size, }; return result; @@ -810,7 +853,7 @@ internal force_inline String8 lnk_symbol_name_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx) { U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx); - return str8(obj->data.str + obj->symbols.name_offsets[primary_idx], obj->symbols.name_sizes[primary_idx]); + return str8(obj->coff.data.str + obj->coff.symbols.name_offsets[primary_idx], obj->coff.symbols.name_sizes[primary_idx]); } internal force_inline COFF_ParsedSymbol @@ -826,13 +869,13 @@ lnk_obj_symbol_patch(LNK_Obj *obj, U64 symbol_idx, COFF_ParsedSymbol patch, LNK_ { U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx); if (flags & LNK_ObjSymbolPatch_Value) { - obj->symbols.values[primary_idx] = patch.value; + obj->coff.symbols.values[primary_idx] = patch.value; } if (flags & LNK_ObjSymbolPatch_Section) { - obj->symbols.section_numbers[primary_idx] = patch.section_number; + obj->coff.symbols.section_numbers[primary_idx] = patch.section_number; } if (flags & LNK_ObjSymbolPatch_StorageClass) { - obj->symbols.storage_classes[primary_idx] = patch.storage_class; + obj->coff.symbols.storage_classes[primary_idx] = patch.storage_class; } } @@ -842,7 +885,7 @@ THREAD_POOL_TASK_FUNC(lnk_collect_obj_chunks_task) LNK_SectionCollector *task = raw_task; LNK_Obj *obj = task->objs[task_id]; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx); if (*section.flags & COFF_SectionFlag_LnkRemove && !task->collect_discarded) { @@ -851,7 +894,7 @@ THREAD_POOL_TASK_FUNC(lnk_collect_obj_chunks_task) String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx); if (str8_match(section_name, task->name, 0)) { - String8 section_data = str8_substr(obj->data, section.frange); + String8 section_data = lnk_obj_section_data_from_sect_idx(obj, sect_idx); str8_list_push(arena, &task->out_lists[task_id], section_data); } } @@ -927,7 +970,7 @@ internal String8List lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj) { String8List drectve_data = {0}; - for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { + for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) { LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx); if (*section.flags & COFF_SectionFlag_LnkInfo) { String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx); @@ -944,7 +987,7 @@ lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj) lnk_error_obj(LNK_Error_IllData, obj, ".drectve must not have relocations"); break; } - str8_list_push(arena, &drectve_data, str8_substr(obj->data, section.frange)); + str8_list_push(arena, &drectve_data, lnk_obj_section_data_from_sect_idx(obj, sect_idx)); } } } @@ -977,7 +1020,7 @@ lnk_symbol_map_from_obj(Arena *arena, LNK_Obj *obj) // count functions U64 count = 0; COFF_ParsedSymbol symbol; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) { count += 1; @@ -988,7 +1031,7 @@ lnk_symbol_map_from_obj(Arena *arena, LNK_Obj *obj) map->v = push_array_no_zero(arena, LNK_SectionOffsetSymbol, count); U64 map_idx = 0; - for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) { + for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) { symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx); if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) { LNK_SectionOffsetSymbol *entry = &map->v[map->count++]; @@ -1036,11 +1079,11 @@ lnk_debug_s_from_obj(Arena *arena, LNK_Obj *obj) String8List raw_debug_s = {0}; { - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx); String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx); if (str8_match(section_name, str8_lit(".debug$S"), 0)) { - String8 debug_s = str8_substr(obj->data, section.frange); + String8 debug_s = lnk_obj_section_data_from_sect_idx(obj, sect_idx); str8_list_push(scratch.arena, &raw_debug_s, debug_s); } } @@ -1099,11 +1142,11 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj) // #define DebugRelocValueFromFileOffset(foff) hash_map_search_u64_u64(&debug_reloc_hm, foff) HashMap debug_reloc_hm = {0}; - for EachIndex(sect_idx, obj->header.section_count_no_null) { + for EachIndex(sect_idx, obj->coff.sections.count) { LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx); if (!str8_match(lnk_obj_section_name_from_sect_idx(obj, sect_idx), str8_lit(".debug$S"), 0)) { continue; } - String8 section_data = str8_substr(obj->data, section.frange); + String8 section_data = lnk_obj_section_data_from_sect_idx(obj, sect_idx); COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section.header); for EachIndex(reloc_idx, relocs.count) { COFF_Reloc *reloc = &relocs.v[reloc_idx]; @@ -1112,12 +1155,12 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj) U64 reloc_size = 0; U64 reloc_value = 0; - if ((obj->header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_Section) || - (obj->header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_Section)) { + if ((obj->coff.header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_Section) || + (obj->coff.header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_Section)) { reloc_size = sizeof(U16); reloc_value = symbol.section_number; - } else if ((obj->header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_SecRel) || - (obj->header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_SecRel)) { + } else if ((obj->coff.header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_SecRel) || + (obj->coff.header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_SecRel)) { reloc_size = sizeof(U32); reloc_value = symbol.value; } @@ -1174,7 +1217,7 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj) // resovle lines header { CV_C13LinesHeader *header = block->header; - U64 header_foff = (U64)(raw_lines.str - obj->data.str) + header->header_off; + U64 header_foff = lnk_obj_foff_from_section_data_ptr(obj, raw_lines.str) + header->header_off; U64 *sec_off = DebugRelocValueFromFileOffset(header_foff + OffsetOf(CV_C13SubSecLinesHeader, sec_off)); if (sec_off) { @@ -1223,9 +1266,8 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj) // build inlinee id -> inlinee name // HashMap inlinee_hm = {0}; - if (obj->debug_t_sect_idx < obj->header.section_count_no_null) { - LNK_ObjSection debug_t_section = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx); - String8 raw_debug_t = str8_substr(obj->data, debug_t_section.frange); + if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) { + String8 raw_debug_t = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx); CV_Signature debug_t_sig = cv_signature_from_debug_s(raw_debug_t); if (debug_t_sig == CV_Signature_C13) { CV_DebugT debug_t = cv_debug_t_from_data(scratch.arena, str8_skip(raw_debug_t, sizeof(CV_Signature)), CV_LeafAlign); @@ -1304,7 +1346,7 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj) if (CV_IsProc32(symbol.kind)) { CV_SymProc32 *proc = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*proc)); if (proc) { - U64 proc_foff = IntFromPtr(symbol.data.str - obj->data.str); + U64 proc_foff = lnk_obj_foff_from_section_data_ptr(obj, symbol.data.str); U64 *off_reloc = DebugRelocValueFromFileOffset(proc_foff + OffsetOf(CV_SymProc32, off)); U64 *sec_reloc = DebugRelocValueFromFileOffset(proc_foff + OffsetOf(CV_SymProc32, sec)); proc_offset = off_reloc ? safe_cast_u32(*off_reloc) : proc->off; diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index 9eb6981b..851b0c77 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -5,20 +5,6 @@ // --- Input ------------------------------------------------------------------- -typedef struct LNK_ObjSymbolArray -{ - U64 count; - U64 *primary_masks; - U32 *block_bases; - U64 *values; - U32 *section_numbers; - COFF_SymbolType *types; - COFF_SymStorageClass *storage_classes; - U8 *aux_counts; - U32 *name_offsets; - U32 *name_sizes; -} LNK_ObjSymbolArray; - typedef U32 LNK_ObjSymbolPatchFlags; enum { @@ -27,39 +13,61 @@ enum LNK_ObjSymbolPatch_StorageClass = (1 << 2), }; +typedef struct LNK_ObjSymbolArray +{ + U64 count; + U64 *primary_masks; + U32 *block_bases; + U64 *values; + U32 *section_numbers; + COFF_SymbolType *types; + COFF_SymStorageClass *storage_classes; + U8 *aux_counts; + U32 *name_offsets; + U32 *name_sizes; +} LNK_ObjSymbolArray; + +typedef struct LNK_ObjSectionArray +{ + U64 count; + COFF_SectionHeader *headers; + COFF_SectionFlags *flags; + String8 *data; + U32 *comdats; + U32Node **associations; +} LNK_ObjSectionArray; + +typedef struct LNK_ObjCoff +{ + String8 data; + COFF_FileHeaderInfo header; + LNK_ObjSectionArray sections; + LNK_ObjSymbolArray symbols; + U32 debug_t_sect_idx; + U32 debug_p_sect_idx; + U32 debug_h_sect_idx; + U32 llvm_addrsig_sect_idx; + B8 hotpatch; +} LNK_ObjCoff; + typedef struct LNK_Obj { String8 path; - String8 data; - COFF_FileHeaderInfo header; - COFF_SectionHeader *section_headers; - COFF_SectionFlags *section_flags; - LNK_ObjSymbolArray symbols; + LNK_ObjCoff coff; // flags - B8 hotpatch; B8 exclude_from_debug_info; U32 input_idx; - // COMDAT - U32 *comdats; - U32Node **associated_sections; - LNK_ObjSymbolRef *symlinks; + // link state + LNK_ObjSymbolRef *symlinks; // link struct LNK_LibMemberRef *link_member; struct LNK_ObjNode *self; - // type info - U32 debug_t_sect_idx; - U32 debug_p_sect_idx; - U32 debug_h_sect_idx; - - // ICF - U32 llvm_addrsig_sect_idx; - // @type_server Rng1U64 ti_range; CV_TypeIndex *ti_map; @@ -242,6 +250,8 @@ internal force_inline String8 lnk_symbol_name_from_coff_symbol_idx(LNK internal void lnk_obj_symbol_patch(LNK_Obj *obj, U64 symbol_idx, COFF_ParsedSymbol patch, LNK_ObjSymbolPatchFlags flags); internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number); +internal String8 lnk_obj_section_data_from_sect_idx(LNK_Obj *obj, U64 sect_idx); +internal U64 lnk_obj_foff_from_section_data_ptr(LNK_Obj *obj, void *ptr); internal U64 lnk_obj_sect_idx_from_section_number(LNK_Obj *obj, U64 section_number); internal U64 lnk_obj_section_number_from_sect_idx(LNK_Obj *obj, U64 sect_idx); internal String8 lnk_obj_section_name_from_section_number(LNK_Obj *obj, U64 section_number); diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index 1873a821..dc82c8ba 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -10,7 +10,7 @@ lnk_symbol_search_type_from_coff(LNK_Obj *obj, COFF_ParsedSymbol symbol, COFF_Sy if (interp == COFF_SymbolValueInterp_Undefined) { search_type = LNK_SymbolSearch_Undefined; } else if (interp == COFF_SymbolValueInterp_Weak) { - COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol, obj->header.is_big_obj); + COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol, obj->coff.header.is_big_obj); switch (weak_ext->characteristics) { case COFF_WeakExt_SearchLibrary: search_type = LNK_SymbolSearch_WeakLibrary; break; case COFF_WeakExt_AntiDependency: search_type = LNK_SymbolSearch_WeakAntiDependency; break; @@ -179,7 +179,7 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src) } LNK_ObjSymbolRef weak_symbol_ref = lnk_ref_from_symbol(weak); - COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak_symbol_ref.obj->header.is_big_obj); + COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak_symbol_ref.obj->coff.header.is_big_obj); if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) { // NOTE: MSVC does not let a weak symbol to replace an undefined one, // but LLD links without errors or warnings, meaning undefined symbols @@ -242,8 +242,8 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src) } // weak vs weak else if (dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Weak) { - COFF_SymbolWeakExt *dst_ext = coff_parse_weak_tag(dst_parsed, dst_ref.obj->header.is_big_obj); - COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src_ref.obj->header.is_big_obj); + COFF_SymbolWeakExt *dst_ext = coff_parse_weak_tag(dst_parsed, dst_ref.obj->coff.header.is_big_obj); + COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src_ref.obj->coff.header.is_big_obj); if ((dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias)) { if (lnk_symbol_is_before(dst, src) || src_ext->characteristics == COFF_WeakExt_AntiDependency) { can_replace = 0; @@ -342,8 +342,8 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src) case COFF_ComdatSelect_ExactMatch: { LNK_ObjSection dst_section = lnk_obj_section_from_section_number(dst_obj, dst_parsed.section_number); LNK_ObjSection src_section = lnk_obj_section_from_section_number(src_obj, src_parsed.section_number); - String8 dst_data = str8_substr(dst_obj->data, dst_section.frange); - String8 src_data = str8_substr(src_obj->data, src_section.frange); + String8 dst_data = lnk_obj_section_data_from_sect_idx(dst_obj, dst_section.sect_idx); + String8 src_data = lnk_obj_section_data_from_sect_idx(src_obj, src_section.sect_idx); B32 is_exact_match = 0; if (dst_check_sum != 0 && src_check_sum != 0) { @@ -396,7 +396,7 @@ lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src) *dst_section.flags |= COFF_SectionFlag_LnkRemove; // remove associated sections from the output - for (U32Node *associated_section = dst_ref.obj->associated_sections[dst_parsed.section_number]; + for (U32Node *associated_section = dst_ref.obj->coff.sections.associations[dst_parsed.section_number]; associated_section != 0; associated_section = associated_section->next) { LNK_ObjSection section = lnk_obj_section_from_section_number(dst_ref.obj, associated_section->data); @@ -728,7 +728,7 @@ lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_Ob break; } - COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->header.is_big_obj); + COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->coff.header.is_big_obj); // no definition -- fallback to default symbol COFF_ParsedSymbol tag_parsed = lnk_parsed_symbol_from_coff_symbol_idx_no_name(current_symbol.obj, weak_ext->tag_index); diff --git a/src/linker/tests/linker_tests.c b/src/linker/tests/linker_tests.c index c4597d3d..a5f8aafd 100644 --- a/src/linker/tests/linker_tests.c +++ b/src/linker/tests/linker_tests.c @@ -5881,8 +5881,12 @@ TEST(debug_p_sig_mismatch) T_Ok(t_write_file(str8_lit("b.obj"), b_obj)); T_Ok(t_write_entry_obj()); - t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj"); + String8 a_obj_before = t_read_file(arena, str8_lit("a.obj")); + String8 b_obj_before = t_read_file(arena, str8_lit("b.obj")); + t_invoke_linkerf("/RAD_MEMORY_MAP_FILES:READ_WRITE /subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj"); T_Ok(g_last_exit_code == 0); + T_Ok(str8_match(a_obj_before, t_read_file(arena, str8_lit("a.obj")), 0)); + T_Ok(str8_match(b_obj_before, t_read_file(arena, str8_lit("b.obj")), 0)); B32 found_error = 0; String8 a_obj_path = t_make_file_path(arena, str8_lit("a.obj")); @@ -6271,8 +6275,14 @@ TEST(gen_rrt) t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full /rad_type_server:foo.rrt a.obj b.obj entry.obj"); T_Ok(g_last_exit_code == 0); - t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash a.obj foo.rrt b.obj entry.obj"); + String8 a_obj_before = t_read_file(arena, a_obj_file_path); + String8 b_obj_before = t_read_file(arena, b_obj_file_path); + String8 rrt_before = t_read_file(arena, str8_lit("foo.rrt")); + t_invoke_linkerf("/RAD_MEMORY_MAP_FILES:READ_WRITE /subsystem:console /entry:entry /out:a.exe /debug:ghash a.obj foo.rrt b.obj entry.obj"); T_Ok(g_last_exit_code == 0); + T_Ok(str8_match(a_obj_before, t_read_file(arena, a_obj_file_path), 0)); + T_Ok(str8_match(b_obj_before, t_read_file(arena, b_obj_file_path), 0)); + T_Ok(str8_match(rrt_before, t_read_file(arena, str8_lit("foo.rrt")), 0)); } TEST(debug_p_and_debug_t_in_obj)