From b50f3094227219ff9bf26083128d9df413d0e450 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Mon, 11 Aug 2025 23:28:03 -0700 Subject: [PATCH] modified member queue logic to prioritize libs where pull-in reference symbol is declared --- src/linker/lnk.c | 30 ++++++++++++++++++++++-------- src/linker/lnk.h | 2 +- src/linker/lnk_symbol_table.c | 10 +++++----- src/linker/lnk_symbol_table.h | 10 ++++------ 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 2d6146a1..9cc82fb7 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -965,18 +965,32 @@ lnk_make_linker_obj(Arena *arena, LNK_Config *config) internal void lnk_queue_lib_member_input(Arena *arena, LNK_Config *config, - LNK_Symbol *symbol, + LNK_Symbol *pull_in_ref, + LNK_Symbol *member_symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list) { - B32 was_live = lnk_mark_symbol_live(symbol); + // lookup member in the lib where pull-in reference is declared + LNK_Symbol *best_match = member_symbol; + for (LNK_Symbol *s = member_symbol; s != 0; s = s->u.member.next) { + if (s->u.member.v.lib == pull_in_ref->u.member.v.lib) { + best_match = s; + break; + } + } + + B32 was_live = lnk_mark_symbol_live(best_match); if (!was_live) { - LNK_SymbolLib *member = &symbol->u.lib; - LNK_Lib *lib = member->lib; - U64 input_idx = Compose64Bit(lib->input_idx, member->member_offset); + LNK_Lib *lib = best_match->u.member.v.lib; + U64 member_offset = best_match->u.member.v.member_offset; + + // compose input index so that members are laid out in the image + // in the order of undefined symbols appearing in objs, + // mimicking serial discovery + U64 input_idx = Compose64Bit(pull_in_ref->u.defined.obj->input_idx, pull_in_ref->u.defined.symbol_idx); // parse member - COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member->member_offset); + COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member_offset); COFF_DataType member_type = coff_data_type_from_data(member_info.data); switch (member_type) { @@ -1159,7 +1173,7 @@ lnk_find_refs(Arena *arena, } if (member_symbol) { - lnk_queue_lib_member_input(arena, config, member_symbol, imports_out, objs_out); + lnk_queue_lib_member_input(arena, config, defn, member_symbol, imports_out, objs_out); MemoryZeroStruct(&ref_symbol); break; } else { @@ -1178,7 +1192,7 @@ lnk_find_refs(Arena *arena, if (defn_interp == COFF_SymbolValueInterp_Undefined) { LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, ref_parsed.name); if (member_symbol) { - lnk_queue_lib_member_input(arena, config, member_symbol, imports_out, objs_out); + lnk_queue_lib_member_input(arena, config, defn, member_symbol, imports_out, objs_out); } break; } else { diff --git a/src/linker/lnk.h b/src/linker/lnk.h index d2150f06..2aa1dc61 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -220,7 +220,7 @@ internal void lnk_push_disallow_lib(Arena *arena, HashTable *disallow_lib_ht, internal void lnk_push_loaded_lib(Arena *arena, HashTable *loaded_lib_ht, String8 path); internal LNK_InputObjList lnk_push_linker_symbols(Arena *arena, LNK_Config *config); -internal void lnk_queue_lib_member_input(Arena *arena, LNK_Config *config, LNK_Symbol *symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list); +internal void lnk_queue_lib_member_input(Arena *arena, LNK_Config *config, LNK_Symbol *pull_in_ref, LNK_Symbol *member_symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list); internal LNK_LinkContext lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config); diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index 4c0f6a0b..c04709a9 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -14,10 +14,10 @@ lnk_make_defined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 sym internal LNK_Symbol * lnk_make_lib_symbol(Arena *arena, String8 name, struct LNK_Lib *lib, U64 member_offset) { - LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1); - symbol->name = name; - symbol->u.lib.lib = lib; - symbol->u.lib.member_offset = member_offset; + LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1); + symbol->name = name; + symbol->u.member.v.lib = lib; + symbol->u.member.v.member_offset = member_offset; return symbol; } @@ -38,7 +38,7 @@ internal B32 lnk_symbol_lib_is_before(void *raw_a, void *raw_b) { LNK_Symbol *a = raw_a, *b = raw_b; - return a->u.lib.lib->input_idx < b->u.lib.lib->input_idx; + return a->u.member.v.lib->input_idx < b->u.member.v.lib->input_idx; } internal void diff --git a/src/linker/lnk_symbol_table.h b/src/linker/lnk_symbol_table.h index 813103e9..2af086fd 100644 --- a/src/linker/lnk_symbol_table.h +++ b/src/linker/lnk_symbol_table.h @@ -24,18 +24,16 @@ typedef struct LNK_SymbolLib U64 member_offset; } LNK_SymbolLib; -typedef struct LNK_SymbolUndefined -{ - struct LNK_Obj *obj; -} LNK_SymbolUndefined; - typedef struct LNK_Symbol { String8 name; B32 is_live; union { LNK_SymbolDefined defined; - LNK_SymbolLib lib; + struct { + struct LNK_Symbol *next; + LNK_SymbolLib v; + } member; } u; } LNK_Symbol;