From 1e1d903878e092e9c99bd7aa241ae98ebada67a2 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Mon, 28 Jul 2025 17:28:52 -0700 Subject: [PATCH] store library pointer in the obj instead of path; required for prioritized symbol lookup implementation --- src/linker/lnk.c | 20 +++++++------- src/linker/lnk_debug_info.c | 4 +-- src/linker/lnk_input.c | 8 ++++++ src/linker/lnk_input.h | 4 ++- src/linker/lnk_obj.c | 53 ++++++++++++++++++------------------- src/linker/lnk_obj.h | 10 +++---- 6 files changed, 55 insertions(+), 44 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 4b7c2e54..a47a4b7d 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1053,7 +1053,7 @@ lnk_queue_lib_member_input(Arena *arena, input->dedup_id = push_str8f(arena, "%S/%S", lib->path, obj_path); input->path = obj_path; input->data = member_info.data; - input->lib_path = lib->path; + input->lib = lib; input->input_idx = input_idx; } break; } @@ -1534,7 +1534,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) { for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Export].first; dir != 0; dir = dir->next) { PE_ExportParse export_parse = {0}; - lnk_parse_export_directive_ex(scratch.arena, dir->value_list, obj->path, obj->lib_path, &export_parse); + lnk_parse_export_directive_ex(scratch.arena, dir->value_list, obj->path, lnk_obj_get_lib_path(obj), &export_parse); lnk_push_export(tp_arena->v[0], export_ht, &export_symbol_list, &include_symbol_list, export_parse); } } @@ -1591,17 +1591,17 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) // /ENTRY for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Entry].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, obj->lib_path); + lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); } // /SUBSYSTEM for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_SubSystem].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, obj->lib_path); + lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); } // /STACK for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Stack].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, obj->lib_path); + lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); } } ProfEnd(); @@ -4812,8 +4812,9 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs 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 section_name = coff_name_from_section_header(string_table, section_header); - if (obj->lib_path.size) { - String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(obj->lib_path)); + if (obj->lib) { + String8 lib_path = lnk_obj_get_lib_path(obj); + String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(lib_path)); String8 obj_name = str8_skip_last_slash(obj->path); str8_list_pushf(temp.arena, &source_list, "%S(%S) SECT%X (%S)", lib_name, obj_name, sect_idx+1, section_name); } else { @@ -4842,8 +4843,9 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs if (lnk_is_coff_section_debug(obj, sect_idx)) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; if (~section_header->flags & COFF_SectionFlag_LnkRemove) { - if (obj->lib_path.size) { - String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(obj->lib_path)); + if (obj->lib) { + String8 lib_path = lnk_obj_get_lib_path(obj); + String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(lib_path)); String8 obj_name = str8_skip_last_slash(obj->path); str8_list_pushf(arena, &map, "%S(%S) SECT%X\n", lib_name, obj_name, sect_idx+1); } else { diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index d2de6b57..42833b3a 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -3133,7 +3133,7 @@ lnk_build_pdb(TP_Context *tp, PDB_DbiModule **mod_arr = push_array(tp_arena->v[0], PDB_DbiModule *, obj_count); for (U64 obj_idx = 0; obj_idx < obj_count; ++obj_idx) { LNK_Obj *obj = obj_arr + obj_idx; - mod_arr[obj_idx] = dbi_push_module(pdb->dbi, obj->path, obj->lib_path); + mod_arr[obj_idx] = dbi_push_module(pdb->dbi, obj->path, lnk_obj_get_lib_path(obj)); // we don't support symbol append Assert(mod_arr[obj_idx]->sn == MSF_INVALID_STREAM_NUMBER); @@ -4502,7 +4502,7 @@ THREAD_POOL_TASK_FUNC(lnk_find_obj_compiler_info_task) dst->compiler_name = comp_info->compiler_name; dst->source_file = str8_zero(); dst->object_file = push_str8_copy(arena, obj->path); - dst->archive_file = push_str8_copy(arena, obj->lib_path); + dst->archive_file = lnk_obj_get_lib_path(obj); dst->build_path = str8_zero(); dst->language = rdi_language_from_cv_language(comp_info->language); diff --git a/src/linker/lnk_input.c b/src/linker/lnk_input.c index 3d690d4c..a7f543bf 100644 --- a/src/linker/lnk_input.c +++ b/src/linker/lnk_input.c @@ -1,6 +1,14 @@ // Copyright (c) 2025 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +internal void +lnk_error_input_obj(LNK_ErrorCode code, LNK_InputObj *input, char *fmt, ...) +{ + va_list args; va_start(args, fmt); + lnk_error_with_loc_fv(code, input->path, input->lib ? input->lib->path : str8_zero(), fmt, args); + va_end(args); +} + internal String8 lnk_string_from_input_source(LNK_InputSourceType input_source) { diff --git a/src/linker/lnk_input.h b/src/linker/lnk_input.h index b802c0ff..f139e39c 100644 --- a/src/linker/lnk_input.h +++ b/src/linker/lnk_input.h @@ -42,7 +42,7 @@ typedef struct LNK_InputObj String8 dedup_id; String8 path; String8 data; - String8 lib_path; + struct LNK_Lib *lib; U64 input_idx; } LNK_InputObj; @@ -55,6 +55,8 @@ typedef struct LNK_InputObjList //////////////////////////////// +internal void lnk_error_input_obj(LNK_ErrorCode code, LNK_InputObj *input, char *fmt, ...); + internal String8 lnk_string_from_input_source(LNK_InputSourceType input_source); internal void lnk_input_obj_list_push_node(LNK_InputObjList *list, LNK_InputObj *node); diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index cde39126..0f1fb974 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -6,7 +6,7 @@ lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...) { va_list args; va_start(args, fmt); String8 obj_path = obj ? obj->path : str8_lit("RADLINK"); - String8 lib_path = obj ? obj->lib_path : str8_zero(); + String8 lib_path = lnk_obj_get_lib_path(obj); lnk_error_with_loc_fv(code, obj_path, lib_path, fmt, args); va_end(args); } @@ -43,7 +43,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) if (header.machine != COFF_MachineType_Unknown) { COFF_MachineType current_machine = ins_atomic_u32_eval_cond_assign(&task->machine, header.machine, COFF_MachineType_Unknown); if (current_machine != COFF_MachineType_Unknown && current_machine != header.machine) { - lnk_error_with_loc(LNK_Error_IncompatibleMachine, input->path, input->lib_path, + lnk_error_input_obj(LNK_Error_IncompatibleMachine, input, "conflicting machine types expected %S but got %S", coff_string_from_machine_type(current_machine), coff_string_from_machine_type(header.machine)); @@ -61,13 +61,13 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) // error check: section table / symbol table / string table // if (raw_coff_section_table.size != dim_1u64(header.section_table_range)) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "corrupted file, unable to read section header table"); + lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read section header table"); } if (raw_coff_symbol_table.size != dim_1u64(header.symbol_table_range)) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "corrupted file, unable to read symbol table"); + lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read symbol table"); } if (raw_coff_string_table.size != dim_1u64(header.string_table_range)) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "corrupted file, unable to read string table"); + lnk_error_input_obj(LNK_Error_IllData, input, "corrupted file, unable to read string table"); } // @@ -86,18 +86,18 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) if (contains_1u64(header.header_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.header_range, sect_range.max-1))) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into file header)", sect_name, sect_idx+1); + lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into file header)", sect_name, sect_idx+1); } if (contains_1u64(header.section_table_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.section_table_range, sect_range.max-1))) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into section header table)", sect_name, sect_idx+1); + lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into section header table)", sect_name, sect_idx+1); } if (contains_1u64(header.symbol_table_range, coff_sect_header->foff) || (coff_sect_header->fsize > 0 && contains_1u64(header.symbol_table_range, sect_range.max-1))) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "header (%S No. %#llx) defines out of bounds section data (file offsets point into symbol table)", sect_name, sect_idx+1); + lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data (file offsets point into symbol table)", sect_name, sect_idx+1); } if (dim_1u64(sect_range) != coff_sect_header->fsize) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "header (%S No. %#llx) defines out of bounds section data", sect_name, sect_idx+1); + lnk_error_input_obj(LNK_Error_IllData, input, "header (%S No. %#llx) defines out of bounds section data", sect_name, sect_idx+1); } } } @@ -116,7 +116,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) 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) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "symbol %S (No. 0x%x) points to an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); + lnk_error_input_obj(LNK_Error_IllData, input, "symbol %S (No. 0x%x) points to an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); } if (symbol.storage_class == COFF_SymStorageClass_Static && symbol.aux_symbol_count > 0) { COFF_ComdatSelectType select; @@ -124,7 +124,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) coff_parse_secdef(symbol, header.is_big_obj, &select, §ion_number, 0, 0); if (select == COFF_ComdatSelect_Associative) { if (section_number == 0 || section_number > header.section_count_no_null) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "section definition symbol %S (No. 0x%x) associates with an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); + lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbol %S (No. 0x%x) associates with an out of bounds section 0x%x", symbol.name, symbol_idx, symbol.section_number); } } } @@ -159,15 +159,15 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) if (comdats[symbol.section_number-1] == ~0) { comdats[symbol.section_number-1] = symbol_idx; } else { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "section definition symbo (No. 0x%llx) tries to ovewrite comdat", symbol_idx); + lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbo (No. 0x%llx) tries to ovewrite comdat", symbol_idx); } } else { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "section size specified by section definition symbol (No 0x%llx) doesn't match size in section header (No. 0x%x); expected 0x%x got 0x%x", symbol_idx, symbol.section_number, section_length, sect_header->fsize); + lnk_error_input_obj(LNK_Error_IllData, input, "section size specified by section definition symbol (No 0x%llx) doesn't match size in section header (No. 0x%x); expected 0x%x got 0x%x", symbol_idx, symbol.section_number, section_length, sect_header->fsize); } } } } else { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "section definition symbol (No. 0x%llx) has out of bounds section number 0x%x", symbol_idx, symbol.section_number); + lnk_error_input_obj(LNK_Error_IllData, input, "section definition symbol (No. 0x%llx) has out of bounds section number 0x%x", symbol_idx, symbol.section_number); } } } @@ -206,7 +206,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) // was section visited? -- loop found if (hash_table_search_u64(visited_sections, curr_section)) { COFF_ParsedSymbol symbol = coff_parse_symbol(header, string_table, symbol_table, comdats[sect_idx]); - lnk_error_with_loc(LNK_Error_AssociativeLoop, input->path, input->lib_path, "section symbol %S (No. 0x%x) does not terminate on a non-associate COMDAT symbol", symbol.name, comdats[sect_idx]); + lnk_error_input_obj(LNK_Error_AssociativeLoop, input, "section symbol %S (No. 0x%x) does not terminate on a non-associate COMDAT symbol", symbol.name, comdats[sect_idx]); break; } @@ -294,7 +294,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) // fill out obj obj->data = input->data; obj->path = push_str8_copy(arena, input->path); - obj->lib_path = push_str8_copy(arena, input->lib_path); + obj->lib = input->lib; obj->input_idx = obj_idx; obj->header = header; obj->comdats = comdats; @@ -483,6 +483,16 @@ lnk_obj_get_vol_md(LNK_Obj *obj) return lnk_obj_match_symbol(obj, str8_lit("@vol.md")).value; } +internal String8 +lnk_obj_get_lib_path(LNK_Obj *obj) +{ + String8 lib_path = {0}; + if (obj && obj->lib) { + lib_path = obj->lib->path; + } + return lib_path; +} + internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number) { @@ -517,17 +527,6 @@ lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj) return symlinks; } -internal String8 -lnk_symlink_from_section_number(LNK_Obj *obj, U64 section_number) -{ - COFF_ParsedSymbol symbol = {0}; - U32 symbol_idx = obj->symlinks[section_number]; - if (symbol_idx != max_U32) { - symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); - } - return symbol.name; -} - internal COFF_RelocArray lnk_coff_reloc_info_from_section_number(LNK_Obj *obj, U64 section_number) { diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index 13e76c80..036ad1d5 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -9,13 +9,12 @@ typedef struct LNK_Obj { String8 data; String8 path; - String8 lib_path; + struct LNK_Lib *lib; U32 input_idx; COFF_FileHeaderInfo header; U32 *comdats; B8 hotpatch; U32Node **associated_sections; - U32 *symlinks; } LNK_Obj; typedef struct LNK_ObjNode @@ -102,9 +101,10 @@ internal LNK_SymbolInputResult lnk_input_obj_symbols(TP_Context *tp, TP_Arena *a // --- Metadata ---------------------------------------------------------------- -internal U32 lnk_obj_get_features(LNK_Obj *obj); -internal U32 lnk_obj_get_comp_id(LNK_Obj *obj); -internal U32 lnk_obj_get_vol_md(LNK_Obj *obj); +internal U32 lnk_obj_get_features(LNK_Obj *obj); +internal U32 lnk_obj_get_comp_id(LNK_Obj *obj); +internal U32 lnk_obj_get_vol_md(LNK_Obj *obj); +internal String8 lnk_obj_get_lib_path(LNK_Obj *obj); // --- Symbol & Section Helpers ------------------------------------------------