diff --git a/src/linker/lnk.c b/src/linker/lnk.c index e3437ab5..7c66679b 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1676,40 +1676,6 @@ lnk_link_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer lnk_link_inputs_(tp, arena, config, inputer, symtab, link, imps, 1); } -internal -THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task) -{ - LNK_ReplaceWeakSymbolsWithDefaultSymbolTask *task = raw_task; - LNK_SymbolTable *symtab = task->symtab; - LNK_SymbolHashTrieChunk *chunk = task->chunks[task_id]; - for EachIndex(i, chunk->count) { - LNK_Symbol *symbol = chunk->v[i].symbol; - COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol); - COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); - if (symbol_interp == COFF_SymbolValueInterp_Weak) { - LNK_SymbolDefined resolve = lnk_resolve_weak_symbol(symtab, symbol->defined); - COFF_ParsedSymbol resolve_parsed = lnk_parsed_symbol_from_coff_symbol_idx(resolve.obj, resolve.symbol_idx); - COFF_SymbolValueInterpType resolve_interp = coff_interp_from_parsed_symbol(resolve_parsed); - if (resolve_interp == COFF_SymbolValueInterp_Weak) { - COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(resolve_parsed, symbol->defined.obj->header.is_big_obj); - if (symbol->defined.obj->header.is_big_obj) { - COFF_Symbol32 *symbol32 = symbol_parsed.raw_symbol; - symbol32->section_number = COFF_Symbol_UndefinedSection; - symbol32->value = 0; - symbol32->storage_class = COFF_SymStorageClass_External; - } else { - COFF_Symbol16 *symbol16 = symbol_parsed.raw_symbol; - symbol16->section_number = COFF_Symbol_UndefinedSection; - symbol16->value = 0; - symbol16->storage_class = COFF_SymStorageClass_External; - } - } else { - symbol->defined = resolve; - } - } - } -} - internal LNK_Link * lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *inputer, LNK_SymbolTable *symtab) { @@ -1945,6 +1911,65 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer // lnk_link_inputs(tp, arena, config, inputer, symtab, link, imps); + // + // finalize symbol table + // + lnk_replace_weak_with_default_symbols(tp, symtab); + + // + // was entry point resolved? + // + if (config->entry_point_name.size == 0 || link->try_to_resolve_entry_point) { + lnk_error(LNK_Error_EntryPoint, "unable to find entry point symbol"); + } + + // + // report undefined symbols + // + { + ProfBegin("Report Unresolved Symbols"); + U64 chunks_count = 0; + LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunks, symtab->arena->count, &chunks_count); + + U64 count = 0; + for EachIndex(chunk_idx, chunks_count) { + LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; + for EachIndex(i, chunk->count) { + LNK_Symbol *symbol = chunk->v[i].symbol; + COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); + if (symbol_interp == COFF_SymbolValueInterp_Undefined) { + count += 1; + } + } + } + + U64 cursor = 0; + LNK_Symbol **unresolved = push_array(scratch.arena, LNK_Symbol *, count); + for EachIndex(chunk_idx, chunks_count) { + LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; + for EachIndex(i, chunk->count) { + LNK_Symbol *symbol = chunk->v[i].symbol; + COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); + if (symbol_interp == COFF_SymbolValueInterp_Undefined) { + unresolved[cursor++] = chunk->v[i].symbol; + } + } + } + + radsort(unresolved, count, lnk_symbol_defined_ptr_is_before); + + for EachIndex(i, count) { + LNK_Symbol *symbol = unresolved[i]; + lnk_error_obj(LNK_Error_UnresolvedSymbol, symbol->defined.obj, "unresolved symbol %S", symbol->name); + } + + // TODO: /FORCE + if (count) { + lnk_exit(LNK_Error_UnresolvedSymbol); + } + ProfEnd(); + } + // // warn about unused delayloads // @@ -1956,77 +1981,6 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer } } - // - // report undefined symbols - // - { - U64 chunks_count = 0; - LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunks, symtab->arena->count, &chunks_count); - - ProfBegin("Replace Unresolved Weak Symbols With Defualt Symbol"); - { - LNK_ReplaceWeakSymbolsWithDefaultSymbolTask task = { .symtab = symtab, .chunks = chunks }; - tp_for_parallel(tp, 0, chunks_count, lnk_replace_weak_with_default_symbol_task, &task); -#if BUILD_DEBUG - for EachIndex(chunk_idx, chunks_count) { - LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; - for EachIndex(i, chunk->count) { - LNK_Symbol *symbol = chunk->v[i].symbol; - COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); - AssertAlways(symbol_interp != COFF_SymbolValueInterp_Weak); - } - } -#endif - } - ProfEnd(); - - - if (config->entry_point_name.size == 0) { - lnk_error(LNK_Error_EntryPoint, "unable to find entry point symbol"); - } - - ProfBegin("Report Unresolved Symbols"); - { - U64 count = 0; - for EachIndex(chunk_idx, chunks_count) { - LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; - for EachIndex(i, chunk->count) { - LNK_Symbol *symbol = chunk->v[i].symbol; - COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); - if (symbol_interp == COFF_SymbolValueInterp_Undefined) { - count += 1; - } - } - } - - U64 cursor = 0; - LNK_Symbol **unresolved = push_array(scratch.arena, LNK_Symbol *, count); - for EachIndex(chunk_idx, chunks_count) { - LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; - for EachIndex(i, chunk->count) { - LNK_Symbol *symbol = chunk->v[i].symbol; - COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); - if (symbol_interp == COFF_SymbolValueInterp_Undefined) { - unresolved[cursor++] = chunk->v[i].symbol; - } - } - } - - radsort(unresolved, count, lnk_symbol_defined_ptr_is_before); - - for EachIndex(i, count) { - LNK_Symbol *symbol = unresolved[i]; - lnk_error_obj(LNK_Error_UnresolvedSymbol, symbol->defined.obj, "unresolved symbol %S", symbol->name); - } - - // TODO: /FORCE - if (count) { - lnk_exit(LNK_Error_UnresolvedSymbol); - } - } - ProfEnd(); - } - // // discard COMDAT sections that are not referenced // diff --git a/src/linker/lnk.h b/src/linker/lnk.h index f26c5f24..e3563083 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -154,12 +154,6 @@ typedef struct LNK_BaseRelocPageArray // --- Workers Contexts -------------------------------------------------------- -typedef struct -{ - LNK_SymbolTable *symtab; - LNK_SymbolHashTrieChunk **chunks; -} LNK_ReplaceWeakSymbolsWithDefaultSymbolTask; - typedef struct { LNK_SymbolTable *symtab; diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index 161ac01d..02f45b5a 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -16,9 +16,10 @@ lnk_symbol_defined_is_before(void *raw_a, void *raw_b) { LNK_Symbol *a = raw_a, *b = raw_b; - - U32 a_lib_input_idx = a->defined.obj->lib ? a->defined.obj->lib->input_idx : 0; - U32 b_lib_input_idx = b->defined.obj->lib ? b->defined.obj->lib->input_idx : 0; + LNK_Lib *a_lib = lnk_obj_get_lib(a->defined.obj); + LNK_Lib *b_lib = lnk_obj_get_lib(b->defined.obj); + U32 a_lib_input_idx = a_lib ? a_lib->input_idx : 0; + U32 b_lib_input_idx = b_lib ? b_lib->input_idx : 0; if (a_lib_input_idx == b_lib_input_idx) { if (a->defined.obj->input_idx == b->defined.obj->input_idx) { @@ -657,6 +658,66 @@ lnk_symbol_table_searchf(LNK_SymbolTable *symtab, char *fmt, ...) return symbol; } +internal +THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task) +{ + LNK_ReplaceWeakSymbolsWithDefaultSymbolTask *task = raw_task; + LNK_SymbolTable *symtab = task->symtab; + LNK_SymbolHashTrieChunk *chunk = task->chunks[task_id]; + for EachIndex(i, chunk->count) { + LNK_Symbol *symbol = chunk->v[i].symbol; + COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol); + COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); + if (symbol_interp == COFF_SymbolValueInterp_Weak) { + LNK_SymbolDefined resolve = lnk_resolve_weak_symbol(symtab, symbol->defined); + COFF_ParsedSymbol resolve_parsed = lnk_parsed_symbol_from_coff_symbol_idx(resolve.obj, resolve.symbol_idx); + COFF_SymbolValueInterpType resolve_interp = coff_interp_from_parsed_symbol(resolve_parsed); + if (resolve_interp == COFF_SymbolValueInterp_Weak) { + COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(resolve_parsed, symbol->defined.obj->header.is_big_obj); + if (symbol->defined.obj->header.is_big_obj) { + COFF_Symbol32 *symbol32 = symbol_parsed.raw_symbol; + symbol32->section_number = COFF_Symbol_UndefinedSection; + symbol32->value = 0; + symbol32->storage_class = COFF_SymStorageClass_External; + } else { + COFF_Symbol16 *symbol16 = symbol_parsed.raw_symbol; + symbol16->section_number = COFF_Symbol_UndefinedSection; + symbol16->value = 0; + symbol16->storage_class = COFF_SymStorageClass_External; + } + } else { + symbol->defined = resolve; + } + } + } +} + +internal void +lnk_replace_weak_with_default_symbols(TP_Context *tp, LNK_SymbolTable *symtab) +{ + Temp scratch = scratch_begin(0,0); + U64 chunks_count = 0; + LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunks, symtab->arena->count, &chunks_count); + + ProfBegin("Replace Unresolved Weak Symbols With Defualt Symbol"); + LNK_ReplaceWeakSymbolsWithDefaultSymbolTask task = { .symtab = symtab, .chunks = chunks }; + tp_for_parallel(tp, 0, chunks_count, lnk_replace_weak_with_default_symbol_task, &task); + +#if BUILD_DEBUG + for EachIndex(chunk_idx, chunks_count) { + LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx]; + for EachIndex(i, chunk->count) { + LNK_Symbol *symbol = chunk->v[i].symbol; + COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol); + AssertAlways(symbol_interp != COFF_SymbolValueInterp_Weak); + } + } +#endif + + scratch_end(scratch); + ProfEnd(); +} + internal ISectOff lnk_sc_from_symbol(LNK_Symbol *symbol) { diff --git a/src/linker/lnk_symbol_table.h b/src/linker/lnk_symbol_table.h index c789a270..04d01ead 100644 --- a/src/linker/lnk_symbol_table.h +++ b/src/linker/lnk_symbol_table.h @@ -78,6 +78,14 @@ typedef struct LNK_SymbolTable LNK_SymbolHashTrieChunkList *chunks; } LNK_SymbolTable; +// --- Workers Contexts -------------------------------------------------------- + +typedef struct +{ + LNK_SymbolTable *symtab; + LNK_SymbolHashTrieChunk **chunks; +} LNK_ReplaceWeakSymbolsWithDefaultSymbolTask; + // --- Symbol Make ------------------------------------------------------------- internal LNK_Symbol * lnk_make_defined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 symbol_idx);