From d3dedd8befa70c0976c6df24098a6705bac94d67 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Mon, 4 Aug 2025 23:33:38 -0700 Subject: [PATCH] simplifying symbol table scopes Linker cannot register extern import symbols initially because the import object files are not available until all other object files are resolved. To work around this, we create a stub weak symbol and assign it to each import symbol. This allows linker to proceed. Once the import object files are generated, linker replaces the stub symbol with the actual ones from the import objects. --- src/linker/lnk.c | 25 ++++++++++++------------- src/linker/lnk.h | 1 + src/linker/lnk_symbol_table.c | 16 ---------------- src/linker/lnk_symbol_table.h | 8 -------- 4 files changed, 13 insertions(+), 37 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index ce3cc0de..87081b2a 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -462,6 +462,12 @@ lnk_make_null_obj(Arena *arena) { COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0,COFF_MachineType_Unknown); + // make import stub + { + COFF_ObjSymbol *tag = coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("RAD_IMPORT_STUB_NULL"), 0, COFF_SymStorageClass_Static); + coff_obj_writer_push_symbol_weak(obj_writer, str8_lit(LNK_IMPORT_STUB), COFF_WeakExt_AntiDependency, tag); + } + // push .debug$T sections with null leaf String8 null_debug_data; { @@ -1026,10 +1032,6 @@ THREAD_POOL_TASK_FUNC(lnk_undef_symbol_finder) if (has_defn) { continue; } - LNK_Symbol *has_import = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Import, symbol->name); - if (has_import) { - continue; - } LNK_Symbol *member_symbol = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Lib, symbol->name); if (member_symbol) { @@ -1059,10 +1061,6 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder) continue; } } - LNK_Symbol *has_import = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Import, symbol->name); - if (has_import) { - continue; - } LNK_Symbol *member_symbol = 0; { @@ -1296,15 +1294,16 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) } // was import already created? - if (lnk_symbol_table_search(symtab, LNK_SymbolScope_Import, import_header.func_name)) { + if (lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, import_header.func_name)) { continue; } // create import stubs (later replaced with acutal imports generated by linker) - LNK_Symbol *thunk_symbol = lnk_make_import_symbol(scratch.arena, import_header.func_name, input->data.coff_import); - LNK_Symbol *imp_symbol = lnk_make_import_symbol(scratch.arena, push_str8f(scratch.arena, "__imp_%S", import_header.func_name), input->data.coff_import); - lnk_symbol_table_push(symtab, LNK_SymbolScope_Import, thunk_symbol); - lnk_symbol_table_push(symtab, LNK_SymbolScope_Import, imp_symbol); + LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit(LNK_IMPORT_STUB)); + LNK_Symbol *thunk_symbol = lnk_make_defined_symbol(scratch.arena, import_header.func_name, import_stub->u.defined.obj, import_stub->u.defined.symbol_idx); + LNK_Symbol *imp_symbol = lnk_make_defined_symbol(scratch.arena, push_str8f(scratch.arena, "__imp_%S", import_header.func_name), import_stub->u.defined.obj, import_stub->u.defined.symbol_idx); + lnk_symbol_table_push(symtab, LNK_SymbolScope_Defined, thunk_symbol); + lnk_symbol_table_push(symtab, LNK_SymbolScope_Defined, imp_symbol); // pick imports hash table HashTable *imports_ht; diff --git a/src/linker/lnk.h b/src/linker/lnk.h index a9e72113..3d7ce197 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -15,6 +15,7 @@ typedef struct LNK_LinkContext // -- Image -------------------------------------------------------------------- +#define LNK_IMPORT_STUB "*** RAD_IMPORT_STUB ***" #define LNK_REMOVED_SECTION_NUMBER_32 (U32)-3 #define LNK_REMOVED_SECTION_NUMBER_16 (U16)-3 diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index e34046da..7d5b5dda 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -21,15 +21,6 @@ lnk_make_lib_symbol(Arena *arena, String8 name, struct LNK_Lib *lib, U64 member_ return symbol; } -internal LNK_Symbol * -lnk_make_import_symbol(Arena *arena, String8 name, String8 import_header) -{ - LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1); - symbol->name = name; - symbol->u.imp.import_header = import_header; - return symbol; -} - internal LNK_Symbol * lnk_make_undefined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj) { @@ -299,9 +290,6 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src) lnk_error(LNK_Error_InvalidPath, "unable to find a suitable replacement logic for symbol combination"); } } break; - case LNK_SymbolScope_Import: { - lnk_error_multiply_defined_symbol(dst, src); - } break; case LNK_SymbolScope_Lib: { // link.exe picks symbol from lib that is discovered first can_replace = lnk_symbol_lib_is_before(src, dst); @@ -344,10 +332,6 @@ lnk_on_symbol_replace(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src) } #endif } break; - case LNK_SymbolScope_Import: { - // illegal to replace imports - InvalidPath; - } break; case LNK_SymbolScope_Lib: { // nothing to replace } break; diff --git a/src/linker/lnk_symbol_table.h b/src/linker/lnk_symbol_table.h index ed1003c5..f6fed011 100644 --- a/src/linker/lnk_symbol_table.h +++ b/src/linker/lnk_symbol_table.h @@ -8,7 +8,6 @@ typedef enum { LNK_SymbolScope_Defined, - LNK_SymbolScope_Import, LNK_SymbolScope_Lib, LNK_SymbolScope_Count } LNK_SymbolScope; @@ -30,18 +29,12 @@ typedef struct LNK_SymbolUndefined struct LNK_Obj *obj; } LNK_SymbolUndefined; -typedef struct LNK_SymbolImport -{ - String8 import_header; -} LNK_SymbolImport; - typedef struct LNK_Symbol { String8 name; union { LNK_SymbolDefined defined; LNK_SymbolLib lib; - LNK_SymbolImport imp; LNK_SymbolUndefined undef; } u; } LNK_Symbol; @@ -120,7 +113,6 @@ typedef struct internal LNK_Symbol * lnk_make_defined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 symbol_idx); internal LNK_Symbol * lnk_make_lib_symbol(Arena *arena, String8 name, struct LNK_Lib *lib, U64 member_offset); internal LNK_Symbol * lnk_make_undefined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj); -internal LNK_Symbol * lnk_make_import_symbol(Arena *arena, String8 name, String8 import_header); // --- Symbol Containers ------------------------------------------------------