WIP switching to serial library search-style, removed lib scope from

the symbol table
This commit is contained in:
Nikita Smith
2025-08-20 16:45:01 -07:00
committed by Ryan Fleury
parent 330c8ead38
commit 67e66dc26e
7 changed files with 462 additions and 517 deletions
+181 -160
View File
@@ -969,22 +969,11 @@ internal void
lnk_queue_lib_member_for_input(Arena *arena,
LNK_Config *config,
LNK_Symbol *pull_in_ref,
LNK_Symbol *member_symbol,
LNK_Lib *lib,
U32 member_idx,
LNK_InputImportList *input_import_list,
LNK_InputObjList *input_obj_list)
{
// 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.defined.obj->lib) {
best_match = s;
break;
}
}
LNK_Lib *lib = best_match->u.member.v.lib;
U32 member_idx = best_match->u.member.v.member_idx;
B32 was_member_queued = ins_atomic_u8_eval_assign(&lib->was_member_queued[member_idx], 1);
if (!was_member_queued) {
U64 member_offset = lib->member_offsets[member_idx];
@@ -992,7 +981,7 @@ lnk_queue_lib_member_for_input(Arena *arena,
// 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);
U64 input_idx = Compose64Bit(pull_in_ref->defined.obj->input_idx, pull_in_ref->defined.symbol_idx);
// parse member
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member_offset);
@@ -1067,20 +1056,20 @@ lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_Obj
String8List roots = str8_list_copy(scratch.arena, &config->include_symbol_list);
// tls
LNK_Symbol *tls_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, MSCRT_TLS_SYMBOL_NAME);
LNK_Symbol *tls_symbol = lnk_symbol_table_searchf(symtab, MSCRT_TLS_SYMBOL_NAME);
if (tls_symbol) {
str8_list_pushf(scratch.arena, &roots, MSCRT_TLS_SYMBOL_NAME);
}
// push tasks for each root symbol
for (String8Node *root_n = roots.first; root_n != 0; root_n = root_n->next) {
LNK_Symbol *root = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, root_n->string);
LNK_Symbol *root = lnk_symbol_table_search(symtab, root_n->string);
struct Task *t = push_array(scratch.arena, struct Task, 1);
t->obj = root->u.defined.obj;
t->obj = root->defined.obj;
t->relocs.count = 1;
t->relocs.v = push_array(scratch.arena, COFF_Reloc, 1);
t->relocs.v[0].isymbol = root->u.defined.symbol_idx;
t->relocs.v[0].isymbol = root->defined.symbol_idx;
SLLStackPush(task_stack, t);
}
@@ -1133,20 +1122,20 @@ lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_Obj
if (ref_interp == COFF_SymbolValueInterp_Regular) {
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(ref_symbol.obj, ref_parsed.section_number);
if (symlink) {
ref_symbol = symlink->u.defined;
ref_symbol = symlink->defined;
}
break;
} else if (ref_interp == COFF_SymbolValueInterp_Undefined) {
if (reloc_parsed.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
next_ref = defn->u.defined;
LNK_Symbol *defn = lnk_symbol_table_search(symtab, ref_parsed.name);
next_ref = defn->defined;
} else {
MemoryZeroStruct(&ref_symbol);
break;
}
} else if (ref_interp == COFF_SymbolValueInterp_Weak) {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
next_ref = defn->u.defined;
LNK_Symbol *defn = lnk_symbol_table_search(symtab, ref_parsed.name);
next_ref = defn->defined;
} else {
break;
}
@@ -1247,12 +1236,12 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task)
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->u.defined);
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->u.defined.obj->header.is_big_obj);
if (symbol->u.defined.obj->header.is_big_obj) {
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;
@@ -1264,7 +1253,7 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task)
symbol16->storage_class = COFF_SymStorageClass_External;
}
} else {
symbol->u.defined = resolve;
symbol->defined = resolve;
}
}
}
@@ -1391,11 +1380,11 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
hash_table_push_string_raw(ht_arena, import_stub_ht, import_header.func_name, 0);
// create import stubs (later replaced with acutal imports generated by linker)
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(symtab->arena->v[0], import_header.func_name, import_stub->u.defined.obj, import_stub->u.defined.symbol_idx);
LNK_Symbol *imp_symbol = lnk_make_defined_symbol(symtab->arena->v[0], 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);
LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, str8_lit(LNK_IMPORT_STUB));
LNK_Symbol *thunk_symbol = lnk_make_defined_symbol(symtab->arena->v[0], import_header.func_name, import_stub->defined.obj, import_stub->defined.symbol_idx);
LNK_Symbol *imp_symbol = lnk_make_defined_symbol(symtab->arena->v[0], push_str8f(scratch.arena, "__imp_%S", import_header.func_name), import_stub->defined.obj, import_stub->defined.symbol_idx);
lnk_symbol_table_push(symtab, thunk_symbol);
lnk_symbol_table_push(symtab, imp_symbol);
// pick imports hash table
HashTable *imports_ht = lnk_is_dll_delay_load(config, import_header.dll_name) ? delayed_imports : static_imports;
@@ -1410,6 +1399,8 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
// push symbol
str8_list_push(scratch.arena, import_symbols, input->data.coff_import);
}
search_flags = SearchFlag_All;
// reset input
MemoryZeroStruct(&input_import_list);
@@ -1528,7 +1519,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
// replace undefined symbols that have an alternate name with a weak symbol
for (LNK_AltNameNode *alt_name_n = config->alt_name_list.first; alt_name_n != 0; alt_name_n = alt_name_n->next) {
LNK_SymbolHashTrie *symbol_ht = lnk_symbol_table_search_(symtab, LNK_SymbolScope_Defined, alt_name_n->data.from);
LNK_SymbolHashTrie *symbol_ht = lnk_symbol_table_search_(symtab, alt_name_n->data.from);
if (symbol_ht) {
COFF_SymbolValueInterpType interp = lnk_interp_from_symbol(symbol_ht->symbol);
if (interp == COFF_SymbolValueInterp_Undefined) {
@@ -1631,8 +1622,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
ProfBegin("Lib Init");
LNK_LibNodeArray libs = lnk_lib_list_push_parallel(tp, tp_arena, &lib_index[input_source], datas, paths);
ProfEnd();
lnk_input_lib_symbols(tp, symtab, libs);
if (lnk_get_log_status(LNK_Log_InputLib)) {
if (libs.count > 0) {
@@ -1669,70 +1658,95 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
} break;
case State_SearchUndefined: {
ProfBegin("Search Undefined");
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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_Undefined) {
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol->name);
if (member_symbol) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
}
}
}
}
}
ProfEnd();
} break;
case State_SearchWeak: {
ProfBegin("Search Weak");
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->u.defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol->name);
if (member_symbol) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
}
}
}
}
}
}
ProfEnd();
} break;
case State_SearchWeakAntiDep: {
ProfBegin("Search Weak AntiDep");
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->u.defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
LNK_SymbolDefined dep_symbol = lnk_resolve_weak_symbol(symtab, symbol->u.defined);
COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dep_symbol.obj, dep_symbol.symbol_idx);
COFF_SymbolValueInterpType dep_interp = coff_interp_from_parsed_symbol(dep_parsed);
if (dep_interp == COFF_SymbolValueInterp_Weak) {
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol_parsed.name);
if (member_symbol) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunks[worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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_Undefined) {
U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list);
}
}
}
}
}
if (input_import_list.count || input_obj_list.count) {
goto end_search_undefined;
}
}
}
end_search_undefined:;
ProfEnd();
} break;
case State_SearchWeak: {
ProfBegin("Search Weak");
for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunks[worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol->name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list);
}
}
}
}
}
}
if (input_import_list.count || input_obj_list.count) {
goto end_search_weak;
}
}
}
end_search_weak:;
ProfEnd();
} break;
case State_SearchWeakAntiDep: {
ProfBegin("Search Weak AntiDep");
for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
for EachIndex(worker_id, symtab->arena->count) {
for (LNK_SymbolHashTrieChunk *c = symtab->chunks[worker_id].first; c != 0; c = c->next) {
for EachIndex(i, c->count) {
LNK_Symbol *symbol = c->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) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
LNK_SymbolDefined dep_symbol = lnk_resolve_weak_symbol(symtab, symbol->defined);
COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dep_symbol.obj, dep_symbol.symbol_idx);
COFF_SymbolValueInterpType dep_interp = coff_interp_from_parsed_symbol(dep_parsed);
if (dep_interp == COFF_SymbolValueInterp_Weak) {
U32 member_idx;
if (lnk_search_lib(&lib_n->data, symbol_parsed.name, &member_idx)) {
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, &lib_n->data, member_idx, &input_import_list, &input_obj_list);
}
}
}
}
}
}
}
if (input_import_list.count || input_obj_list.count) {
goto end_search_antidep;
}
}
}
end_search_antidep:;
ProfEnd();
} break;
case State_SearchEntryPoint: {
@@ -1748,23 +1762,28 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
for EachIndex(subsys_idx, PE_WindowsSubsystem_COUNT) {
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
for EachIndex(entry_idx, name_arr.count) {
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
entry_point_symbol = lnk_symbol_table_search(symtab, name_arr.v[entry_idx]);
if (entry_point_symbol) {
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
config->entry_point_name = name_arr.v[entry_idx];
goto dbl_break;
}
}
}
// search for potential entry points in libs
if (!entry_point_symbol) {
if (config->entry_point_name.size) {
for EachIndex(subsys_idx, PE_WindowsSubsystem_COUNT) {
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
for EachIndex(entry_idx, name_arr.count) {
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
if (entry_point_symbol) {
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
goto dbl_break;
for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
if (lnk_search_lib(&lib_n->data, name_arr.v[entry_idx], 0)) {
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
config->entry_point_name = name_arr.v[entry_idx];
goto dbl_break;
}
}
}
}
}
@@ -1776,42 +1795,44 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
// and see which is in the symbol table
String8Array name_arr = pe_get_entry_point_names(config->machine, config->subsystem, config->file_characteristics);
for EachIndex(entry_idx, name_arr.count) {
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, name_arr.v[entry_idx]);
if (symbol) {
if (entry_point_symbol) {
if (config->entry_point_name.size) {
lnk_error(LNK_Error_EntryPoint,
"multiple entry point symbols found: %S(%S) and %S(%S)",
entry_point_symbol->name, entry_point_symbol->u.defined.obj->path,
symbol->name, symbol->u.defined.obj->path);
entry_point_symbol->name, entry_point_symbol->defined.obj->path,
symbol->name, symbol->defined.obj->path);
} else {
entry_point_symbol = symbol;
config->entry_point_name = name_arr.v[entry_idx];
}
}
}
// search for entry point in libs
if (!entry_point_symbol) {
if (!config->entry_point_name.size) {
for EachIndex(entry_idx, name_arr.count) {
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
if (entry_point_symbol) {
break;
for EachIndex(i, ArrayCount(lib_index)) {
for (LNK_LibNode *lib_n = lib_index[i].first; lib_n != 0; lib_n = lib_n->next) {
if (lnk_search_lib(&lib_n->data, name_arr.v[entry_idx], 0)) {
config->entry_point_name = name_arr.v[entry_idx];
goto dbl_break2;
}
}
}
}
dbl_break2:;
}
}
// redirect user entry to appropriate CRT entry
if (entry_point_symbol) {
config->entry_point_name = entry_point_symbol->name;
if (str8_match_lit("wmain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("wmainCRTStartup");
} else if (str8_match_lit("main", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("mainCRTStartup");
} else if (str8_match_lit("WinMain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("WinMainCRTStartup");
} else if (str8_match_lit("wWinMain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("wWinMainCRTStartup");
}
if (str8_match_lit("wmain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("wmainCRTStartup");
} else if (str8_match_lit("main", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("mainCRTStartup");
} else if (str8_match_lit("WinMain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("WinMainCRTStartup");
} else if (str8_match_lit("wWinMain", config->entry_point_name, 0)) {
config->entry_point_name = str8_lit("wWinMainCRTStartup");
}
}
@@ -1822,7 +1843,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
str8_list_push(scratch.arena, &value_strings, config->entry_point_name);
lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, 0);
}
// no entry point, error and exit
// no entry point, print out error and exit
else {
lnk_error(LNK_Error_EntryPoint, "unable to find entry point symbol");
}
@@ -1968,7 +1989,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
if (!exp->is_forwarder) {
// filter out unresolved exports
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, exp_n->data.name);
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, exp_n->data.name);
if (symbol == 0) {
lnk_error_with_loc(LNK_Warning_IllExport, exp->obj_path, exp->lib_path, "unresolved export symbol %S\n", exp->name);
continue;
@@ -2170,7 +2191,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
{
U64 chunks_count = 0;
LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunk_lists[LNK_SymbolScope_Defined], symtab->arena->count, &chunks_count);
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");
{
@@ -2220,7 +2241,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
for EachIndex(i, count) {
LNK_Symbol *symbol = unresolved[i];
lnk_error_obj(LNK_Error_UnresolvedSymbol, symbol->u.defined.obj, "unresolved symbol %S", symbol->name);
lnk_error_obj(LNK_Error_UnresolvedSymbol, symbol->defined.obj, "unresolved symbol %S", symbol->name);
}
// TODO: /FORCE
@@ -2289,34 +2310,34 @@ lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_SymbolDefined symbol, LNK_Symbol
switch (symbol_interp) {
case COFF_SymbolValueInterp_Regular: {
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(symbol.obj, symbol_parsed.section_number);
*symbol_out = symlink ? symlink->u.defined : symbol;
*symbol_out = symlink ? symlink->defined : symbol;
} break;
case COFF_SymbolValueInterp_Weak: {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol_parsed.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn->u.defined.obj, defn->u.defined.symbol_idx);
LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn->defined.obj, defn->defined.symbol_idx);
COFF_SymbolValueInterpType defn_interp = coff_interp_symbol(defn_parsed.section_number, defn_parsed.value, defn_parsed.storage_class);
if (defn_interp != COFF_SymbolValueInterp_Undefined) {
*symbol_out = defn->u.defined;
*symbol_out = defn->defined;
} else {
is_resolved = 0;
}
} break;
case COFF_SymbolValueInterp_Undefined: {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol_parsed.name);
LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name);
if (defn) {
*symbol_out = defn->u.defined;
*symbol_out = defn->defined;
} else {
is_resolved = 0;
}
} break;
case COFF_SymbolValueInterp_Common: {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol_parsed.name);
*symbol_out = defn->u.defined;
LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name);
*symbol_out = defn->defined;
} break;
case COFF_SymbolValueInterp_Abs: {
if (symbol_parsed.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, symbol_parsed.name);
*symbol_out = defn->u.defined;
LNK_Symbol *defn = lnk_symbol_table_search(symtab, symbol_parsed.name);
*symbol_out = defn->defined;
} else {
*symbol_out = symbol;
}
@@ -2442,7 +2463,7 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
if (symlink == 0) { continue; }
COFF_ParsedSymbol symlink_parsed = lnk_parsed_symbol_from_defined(symlink);
task->sect_map[obj_idx][sect_idx] = task->sect_map[symlink->u.defined.obj->input_idx][symlink_parsed.section_number - 1];
task->sect_map[obj_idx][sect_idx] = task->sect_map[symlink->defined.obj->input_idx][symlink_parsed.section_number - 1];
}
ProfEnd();
}
@@ -2485,12 +2506,12 @@ THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task)
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) {
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(obj, symbol.section_number);
if (symlink && symlink->u.defined.obj != obj) {
if (symlink && symlink->defined.obj != obj) {
U32 section_number;
U32 value;
if (symbol.storage_class == COFF_SymStorageClass_External) {
// COMDAT leader may be at a different offset, so update this symbol with leader's offset
COFF_ParsedSymbol parsed_symlink = lnk_parsed_symbol_from_coff_symbol_idx(symlink->u.defined.obj, symlink->u.defined.symbol_idx);
COFF_ParsedSymbol parsed_symlink = lnk_parsed_symbol_from_coff_symbol_idx(symlink->defined.obj, symlink->defined.symbol_idx);
section_number = symbol.section_number;
value = parsed_symlink.value;
} else {
@@ -2548,10 +2569,10 @@ lnk_common_block_contrib_is_before(void *raw_a, void *raw_b)
if (a->u.size == b->u.size) {
LNK_Symbol *a_symbol = a->symbol;
LNK_Symbol *b_symbol = b->symbol;
if (a_symbol->u.defined.obj->input_idx == b_symbol->u.defined.obj->input_idx) {
is_before = a_symbol->u.defined.symbol_idx < b_symbol->u.defined.symbol_idx;
if (a_symbol->defined.obj->input_idx == b_symbol->defined.obj->input_idx) {
is_before = a_symbol->defined.symbol_idx < b_symbol->defined.symbol_idx;
} else {
is_before = a_symbol->u.defined.obj->input_idx < b_symbol->u.defined.obj->input_idx;
is_before = a_symbol->defined.obj->input_idx < b_symbol->defined.obj->input_idx;
}
} else {
is_before = a->u.size > b->u.size;
@@ -2571,8 +2592,8 @@ THREAD_POOL_TASK_FUNC(lnk_patch_common_block_leaders_task)
for (U64 contrib_idx = contrib_range.min; contrib_idx < contrib_range.max; contrib_idx += 1) {
LNK_CommonBlockContrib *contrib = &task->u.patch_symtabs.common_block_contribs[contrib_idx];
LNK_Symbol *symbol = contrib->symbol;
LNK_Obj *obj = symbol->u.defined.obj;
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol->u.defined.symbol_idx);
LNK_Obj *obj = symbol->defined.obj;
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol->defined.symbol_idx);
U64 section_number = task->u.patch_symtabs.common_block_sect->sect_idx + 1;
if (obj->header.is_big_obj) {
@@ -2585,7 +2606,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_common_block_leaders_task)
symbol16->section_number = safe_cast_u16(section_number);
}
task->u.patch_symtabs.was_symbol_patched[obj->input_idx][symbol->u.defined.symbol_idx] = 1;
task->u.patch_symtabs.was_symbol_patched[obj->input_idx][symbol->defined.symbol_idx] = 1;
}
ProfEnd();
@@ -2605,8 +2626,8 @@ THREAD_POOL_TASK_FUNC(lnk_patch_common_block_symbols_task)
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Common) {
LNK_Symbol *defn = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn->u.defined.obj, defn->u.defined.symbol_idx);
LNK_Symbol *defn = lnk_symbol_table_search(task->symtab, symbol.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn->defined.obj, defn->defined.symbol_idx);
Assert(coff_interp_symbol(defn_parsed.section_number, defn_parsed.value, defn_parsed.storage_class) == COFF_SymbolValueInterp_Regular);
if (defn) {
if (obj->header.is_big_obj) {
@@ -2880,10 +2901,10 @@ THREAD_POOL_TASK_FUNC(lnk_count_common_block_contribs_task)
LNK_BuildImageTask *task = raw_task;
LNK_SymbolTable *symtab = task->symtab;
for (LNK_SymbolHashTrieChunk *chunk = symtab->chunk_lists[LNK_SymbolScope_Defined][task_id].first; chunk != 0; chunk = chunk->next) {
for (LNK_SymbolHashTrieChunk *chunk = symtab->chunks[task_id].first; chunk != 0; chunk = chunk->next) {
for EachIndex(i, chunk->count) {
LNK_Symbol *symbol = chunk->v[i].symbol;
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, symbol->u.defined.symbol_idx);
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->defined.obj, symbol->defined.symbol_idx);
COFF_SymbolValueInterpType parsed_interp = coff_interp_symbol(parsed_symbol.section_number, parsed_symbol.value, parsed_symbol.storage_class);
if (parsed_interp == COFF_SymbolValueInterp_Common) {
task->u.common_block.counts[task_id] += 1;
@@ -2899,10 +2920,10 @@ THREAD_POOL_TASK_FUNC(lnk_fill_out_common_block_contribs_task)
LNK_SymbolTable *symtab = task->symtab;
U64 cursor = task->u.common_block.offsets[task_id];
for (LNK_SymbolHashTrieChunk *chunk = symtab->chunk_lists[LNK_SymbolScope_Defined][task_id].first; chunk != 0; chunk = chunk->next) {
for (LNK_SymbolHashTrieChunk *chunk = symtab->chunks[task_id].first; chunk != 0; chunk = chunk->next) {
for EachIndex(i, chunk->count) {
LNK_Symbol *symbol = chunk->v[i].symbol;
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, symbol->u.defined.symbol_idx);
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->defined.obj, symbol->defined.symbol_idx);
COFF_SymbolValueInterpType parsed_interp = coff_interp_symbol(parsed_symbol.section_number, parsed_symbol.value, parsed_symbol.storage_class);
if (parsed_interp == COFF_SymbolValueInterp_Common) {
LNK_CommonBlockContrib *contrib = &task->u.common_block.contribs[cursor++];
@@ -3833,7 +3854,7 @@ lnk_build_win32_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config
COFF_SectionHeader **section_table = push_array(arena, COFF_SectionHeader *, coff_section_table_count + 1);
for (U64 i = 1; i <= coff_section_table_count; i += 1) { section_table[i] = &coff_section_table[i-1]; }
LNK_Symbol *entry_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, config->entry_point_name);
LNK_Symbol *entry_symbol = lnk_symbol_table_search(symtab, config->entry_point_name);
if (entry_symbol) {
*entry_point_va = safe_cast_u32(lnk_virt_off_from_symbol(section_table, entry_symbol));
}
@@ -4272,7 +4293,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// patch load config
{
LNK_Symbol *load_config_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME));
LNK_Symbol *load_config_symbol = lnk_symbol_table_search(symtab, str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME));
if (load_config_symbol) {
U64 load_config_foff = lnk_file_off_from_symbol(image_section_table, load_config_symbol);
String8 load_config_data = str8_skip(image_data, load_config_foff);
@@ -4326,16 +4347,16 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// patch import and import addr
{
LNK_Section *idata_sect = lnk_section_table_search(sectab, str8_lit(".idata"), PE_IDATA_SECTION_FLAGS);
LNK_Symbol *null_import_desc = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, "__NULL_IMPORT_DESCRIPTOR");
LNK_Symbol *null_thunk_data = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, "\x7f%S_NULL_THUNK_DATA", lnk_get_image_name(config));
LNK_Symbol *null_import_desc = lnk_symbol_table_searchf(symtab, "__NULL_IMPORT_DESCRIPTOR");
LNK_Symbol *null_thunk_data = lnk_symbol_table_searchf(symtab, "\x7f%S_NULL_THUNK_DATA", lnk_get_image_name(config));
if (idata_sect && null_import_desc && null_thunk_data) {
COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_import_desc->u.defined.obj, null_import_desc->u.defined.symbol_idx);
COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_import_desc->defined.obj, null_import_desc->defined.symbol_idx);
LNK_SectionContrib *idata_first_contrib = lnk_get_first_section_contrib(idata_sect);
PE_DataDirectory *import_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_IMPORT);
import_dir->virt_off = image_section_table[idata_first_contrib->u.sect_idx + 1]->voff + idata_first_contrib->u.off;
import_dir->virt_size = null_import_desc_parsed.value - idata_first_contrib->u.off;
COFF_ParsedSymbol null_thunk_data_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_thunk_data->u.defined.obj, null_thunk_data->u.defined.symbol_idx);
COFF_ParsedSymbol null_thunk_data_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_thunk_data->defined.obj, null_thunk_data->defined.symbol_idx);
U64 null_thunk_data_voff = image_section_table[null_thunk_data_parsed.section_number]->voff + null_thunk_data_parsed.value;
U64 first_import_foff = image_section_table[idata_first_contrib->u.sect_idx+1]->foff + idata_first_contrib->u.off;
PE_ImportEntry *first_import = str8_deserial_get_raw_ptr(image_data, first_import_foff, sizeof(*first_import));
@@ -4348,10 +4369,10 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// patch delay imports
{
LNK_Section *didat_sect = lnk_section_table_search(sectab, str8_lit(".didat"), PE_IDATA_SECTION_FLAGS);
LNK_Symbol *null_import_desc = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR"));
LNK_Symbol *last_null_thunk = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, "\x7f%S_NULL_THUNK_DATA_DLA", lnk_get_image_name(config));
LNK_Symbol *null_import_desc = lnk_symbol_table_search(symtab, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR"));
LNK_Symbol *last_null_thunk = lnk_symbol_table_searchf(symtab,"\x7f%S_NULL_THUNK_DATA_DLA", lnk_get_image_name(config));
if (didat_sect && null_import_desc && last_null_thunk) {
COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_import_desc->u.defined.obj, null_import_desc->u.defined.symbol_idx);
COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_import_desc->defined.obj, null_import_desc->defined.symbol_idx);
LNK_SectionContrib *didat_first_contrib = lnk_get_first_section_contrib(didat_sect);
PE_DataDirectory *import_dir = pe_data_directory_from_idx(image_data, pe, PE_DataDirectoryIndex_DELAY_IMPORT);
import_dir->virt_off = lnk_get_first_section_contrib_voff(image_section_table, didat_sect);
@@ -4361,7 +4382,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// patch TLS
{
LNK_Symbol *tls_used_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, MSCRT_TLS_SYMBOL_NAME);
LNK_Symbol *tls_used_symbol = lnk_symbol_table_searchf(symtab, MSCRT_TLS_SYMBOL_NAME);
if (tls_used_symbol) {
ProfBegin("Patch TLS");
@@ -4441,8 +4462,8 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// compute image guid, and patch PDB and RDI guids
{
LNK_Symbol *guid_pdb_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit("RAD_LINK_PE_DEBUG_GUID_PDB"));
LNK_Symbol *guid_rdi_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit("RAD_LINK_PE_DEBUG_GUID_RDI"));
LNK_Symbol *guid_pdb_symbol = lnk_symbol_table_search(symtab, str8_lit("RAD_LINK_PE_DEBUG_GUID_PDB"));
LNK_Symbol *guid_rdi_symbol = lnk_symbol_table_search(symtab, str8_lit("RAD_LINK_PE_DEBUG_GUID_RDI"));
if (guid_pdb_symbol || guid_rdi_symbol) {
switch (config->guid_type) {
+1 -10
View File
@@ -175,15 +175,6 @@ typedef struct
U128 *hashes;
} LNK_Blake3Hasher;
typedef struct
{
LNK_SymbolTable *symtab;
union {
LNK_ObjNodeArray objs;
LNK_LibNodeArray libs;
} u;
} LNK_SymbolPusher;
// --- Config -----------------------------------------------------------------
internal LNK_Config * lnk_config_from_argcv(Arena *arena, int argc, char **argv);
@@ -221,7 +212,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 *pull_in_ref, LNK_Symbol *member_symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list);
internal void lnk_queue_lib_member_for_input(Arena *arena, LNK_Config *config, LNK_Symbol *pull_in_ref, LNK_Lib *lib, U32 member_idx, 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);
+3 -3
View File
@@ -3023,7 +3023,7 @@ THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_defined_task)
LNK_Symbol *symbol = chunk->v[i].symbol;
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol->u.defined.obj)) { continue; }
if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol->defined.obj)) { continue; }
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; }
@@ -3072,8 +3072,8 @@ lnk_build_pdb_public_symbols(TP_Context *tp,
ProfBegin("Defined");
LNK_BuildPublicSymbolsTask task = {0};
task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, tp->worker_count);
task.chunk_lists = symtab->chunk_lists[LNK_SymbolScope_Defined];
task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, tp->worker_count);
task.chunk_lists = symtab->chunks;
tp_for_parallel(tp, arena, tp->worker_count, lnk_build_pdb_public_symbols_defined_task, &task);
ProfEnd();
+9 -20
View File
@@ -221,29 +221,18 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, S
return result;
}
internal
THREAD_POOL_TASK_FUNC(lnk_push_lib_symbols_task)
internal B32
lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out)
{
LNK_SymbolPusher *task = raw_task;
LNK_SymbolTable *symtab = task->symtab;
LNK_Lib *lib = &task->u.libs.v[task_id].data;
// TODO: symbol names are already sorted, replace with binary search
for EachIndex(symbol_idx, lib->symbol_count) {
U32 member_offset_number = lib->symbol_indices[symbol_idx];
if (member_offset_number > 0) {
LNK_Symbol *symbol = lnk_make_lib_symbol(arena, lib->symbol_names.v[symbol_idx], lib, member_offset_number-1);
lnk_symbol_table_push_(symtab, arena, worker_id, LNK_SymbolScope_Lib, symbol);
if (str8_match(lib->symbol_names.v[symbol_idx], symbol_name, 0)) {
if (member_idx_out) {
*member_idx_out = lib->symbol_indices[symbol_idx] - 1;
}
return 1;
}
}
}
internal void
lnk_input_lib_symbols(TP_Context *tp, LNK_SymbolTable *symtab, LNK_LibNodeArray libs)
{
ProfBeginFunction();
LNK_SymbolPusher task = {0};
task.symtab = symtab;
task.u.libs = libs;
tp_for_parallel(tp, symtab->arena, libs.count, lnk_push_lib_symbols_task, &task);
ProfEnd();
return 0;
}
+6 -6
View File
@@ -345,27 +345,27 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
break;
}
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, defn);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
}
} break;
case COFF_SymbolValueInterp_Weak: {
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, defn);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} break;
case COFF_SymbolValueInterp_Undefined: {
if (symbol.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, defn);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
}
} break;
case COFF_SymbolValueInterp_Common: {
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, defn);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
} break;
case COFF_SymbolValueInterp_Abs: {
if (symbol.storage_class == COFF_SymStorageClass_External) {
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, defn);
lnk_symbol_table_push_(task->symtab, arena, worker_id, defn);
}
} break;
case COFF_SymbolValueInterp_Debug: {
@@ -388,7 +388,7 @@ lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj)
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number);
if (sect_header->flags & COFF_SectionFlag_LnkCOMDAT) {
if (symlinks[symbol.section_number] == 0 || symbol.value == 0) {
symlinks[symbol.section_number] = lnk_symbol_table_search_(symtab, LNK_SymbolScope_Defined, symbol.name);
symlinks[symbol.section_number] = lnk_symbol_table_search_(symtab, symbol.name);
}
}
}
+254 -290
View File
@@ -6,18 +6,8 @@ lnk_make_defined_symbol(Arena *arena, String8 name, struct LNK_Obj *obj, U32 sym
{
LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1);
symbol->name = name;
symbol->u.defined.obj = obj;
symbol->u.defined.symbol_idx = symbol_idx;
return symbol;
}
internal LNK_Symbol *
lnk_make_lib_symbol(Arena *arena, String8 name, struct LNK_Lib *lib, U32 member_idx)
{
LNK_Symbol *symbol = push_array(arena, LNK_Symbol, 1);
symbol->name = name;
symbol->u.member.v.lib = lib;
symbol->u.member.v.member_idx = member_idx;
symbol->defined.obj = obj;
symbol->defined.symbol_idx = symbol_idx;
return symbol;
}
@@ -25,7 +15,7 @@ internal B32
lnk_symbol_defined_is_before(void *raw_a, void *raw_b)
{
LNK_Symbol *a = raw_a, *b = raw_b;
return a->u.defined.obj->input_idx < b->u.defined.obj->input_idx;
return a->defined.obj->input_idx < b->defined.obj->input_idx;
}
internal B32
@@ -34,13 +24,6 @@ lnk_symbol_defined_ptr_is_before(void *raw_a, void *raw_b)
return lnk_symbol_defined_is_before(*(LNK_Symbol **)raw_a, *(LNK_Symbol **)raw_b);
}
internal B32
lnk_symbol_lib_is_before(void *raw_a, void *raw_b)
{
LNK_Symbol *a = raw_a, *b = raw_b;
return a->u.member.v.lib->input_idx < b->u.member.v.lib->input_idx;
}
internal void
lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node)
{
@@ -125,281 +108,265 @@ lnk_symbol_hash_trie_chunk_list_push(Arena *arena, LNK_SymbolHashTrieChunkList *
internal void
lnk_error_multiply_defined_symbol(LNK_Symbol *dst, LNK_Symbol *src)
{
lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, dst->u.defined.obj, "symbol \"%S\" (No. %#x) is multiply defined in %S (No. %#x)", dst->name, dst->u.defined.symbol_idx, src->u.defined.obj->path, src->u.defined.symbol_idx);
lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, dst->defined.obj, "symbol \"%S\" (No. %#x) is multiply defined in %S (No. %#x)", dst->name, dst->defined.symbol_idx, src->defined.obj->path, src->defined.symbol_idx);
}
internal B32
lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
{
B32 can_replace = 0;
switch (scope) {
case LNK_SymbolScope_Defined: {
LNK_Obj *dst_obj = dst->u.defined.obj;
LNK_Obj *src_obj = src->u.defined.obj;
COFF_ParsedSymbol dst_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dst->u.defined.obj, dst->u.defined.symbol_idx);
COFF_ParsedSymbol src_parsed = lnk_parsed_symbol_from_coff_symbol_idx(src->u.defined.obj, src->u.defined.symbol_idx);
COFF_SymbolValueInterpType dst_interp = coff_interp_from_parsed_symbol(dst_parsed);
COFF_SymbolValueInterpType src_interp = coff_interp_from_parsed_symbol(src_parsed);
// undefined vs regular
if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Regular) {
can_replace = 1;
}
// (weak vs undefined) or (undefined vs weak)
else if ((dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Undefined) || (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Weak)) {
LNK_Symbol *weak, *undef;
COFF_ParsedSymbol weak_parsed;
if (dst_interp == COFF_SymbolValueInterp_Weak) {
weak = dst, undef = src;
weak_parsed = dst_parsed;
} else {
weak = src, undef = dst;
weak_parsed = src_parsed;
}
LNK_Obj *dst_obj = dst->defined.obj;
LNK_Obj *src_obj = src->defined.obj;
COFF_ParsedSymbol dst_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dst->defined.obj, dst->defined.symbol_idx);
COFF_ParsedSymbol src_parsed = lnk_parsed_symbol_from_coff_symbol_idx(src->defined.obj, src->defined.symbol_idx);
COFF_SymbolValueInterpType dst_interp = coff_interp_from_parsed_symbol(dst_parsed);
COFF_SymbolValueInterpType src_interp = coff_interp_from_parsed_symbol(src_parsed);
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak->u.defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
can_replace = lnk_symbol_defined_is_before(dst, src);
} else if (weak_ext->characteristics == COFF_WeakExt_NoLibrary) {
can_replace = dst_interp == COFF_SymbolValueInterp_Weak;
} else if (weak_ext->characteristics == COFF_WeakExt_SearchAlias) {
can_replace = dst_interp == COFF_SymbolValueInterp_Undefined;
} else {
can_replace = lnk_symbol_defined_is_before(src, dst);
}
// undefined vs regular
if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Regular) {
can_replace = 1;
}
// (weak vs undefined) or (undefined vs weak)
else if ((dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Undefined) || (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Weak)) {
LNK_Symbol *weak, *undef;
COFF_ParsedSymbol weak_parsed;
if (dst_interp == COFF_SymbolValueInterp_Weak) {
weak = dst, undef = src;
weak_parsed = dst_parsed;
} else {
weak = src, undef = dst;
weak_parsed = src_parsed;
}
// undefined vs undefined
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak->defined.obj->header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
can_replace = lnk_symbol_defined_is_before(dst, src);
} else if (weak_ext->characteristics == COFF_WeakExt_NoLibrary) {
can_replace = dst_interp == COFF_SymbolValueInterp_Weak;
} else if (weak_ext->characteristics == COFF_WeakExt_SearchAlias) {
can_replace = dst_interp == COFF_SymbolValueInterp_Undefined;
} else {
can_replace = lnk_symbol_defined_is_before(src, dst);
}
// undefined vs common
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Common) {
}
// undefined vs undefined
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
can_replace = lnk_symbol_defined_is_before(src, dst);
}
// undefined vs common
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Common) {
can_replace = 1;
}
// undefined vs abs
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Abs) {
can_replace = 1;
}
// undefined vs debug
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Debug) {
can_replace = 1;
}
// regular/common/abs/debug vs undefined
else if (dst_interp != COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
can_replace = 0;
}
// regular vs abs
else if (dst_interp == COFF_SymbolValueInterp_Regular && src_interp == COFF_SymbolValueInterp_Abs) {
lnk_error_multiply_defined_symbol(dst, src);
}
// abs vs regular
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Regular) {
lnk_error_multiply_defined_symbol(dst, src);
}
// abs vs common
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Common) {
if (lnk_symbol_defined_is_before(dst, src)) {
can_replace = 1;
}
// undefined vs abs
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Abs) {
can_replace = 1;
}
// undefined vs debug
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Debug) {
can_replace = 1;
}
// regular/common/abs/debug vs undefined
else if (dst_interp != COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
can_replace = 0;
}
// regular vs abs
else if (dst_interp == COFF_SymbolValueInterp_Regular && src_interp == COFF_SymbolValueInterp_Abs) {
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
// abs vs regular
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Regular) {
}
// common vs abs
else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Abs) {
if (lnk_symbol_defined_is_before(dst, src)) {
lnk_error_multiply_defined_symbol(dst, src);
}
// abs vs common
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Common) {
if (lnk_symbol_defined_is_before(dst, src)) {
can_replace = 1;
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
}
// common vs abs
else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Abs) {
if (lnk_symbol_defined_is_before(dst, src)) {
lnk_error_multiply_defined_symbol(dst, src);
}
}
// abs vs abs
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Abs) {
lnk_error_multiply_defined_symbol(dst, 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->u.defined.obj->header.is_big_obj);
COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src->u.defined.obj->header.is_big_obj);
if ((dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias)) {
if (lnk_symbol_defined_is_before(dst, src) || src_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 0;
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} else if (dst_ext->characteristics != COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) {
if (lnk_symbol_defined_is_before(src, dst) || dst_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 1;
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} else if (dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) {
lnk_error_multiply_defined_symbol(dst, src);
} else {
can_replace = lnk_symbol_defined_is_before(src, dst);
}
}
// weak vs regular/abs/common
else if (dst_interp == COFF_SymbolValueInterp_Weak && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Abs || src_interp == COFF_SymbolValueInterp_Common)) {
can_replace = 1;
}
// regular/abs/common vs weak
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Abs || dst_interp == COFF_SymbolValueInterp_Common) && src_interp == COFF_SymbolValueInterp_Weak) {
can_replace = 0;
}
// regular/common vs regular/common
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Common) && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common)) {
// parse dst symbol properties
B32 dst_is_comdat = 0;
COFF_ComdatSelectType dst_select;
U32 dst_section_length;
U32 dst_check_sum;
if (dst_interp == COFF_SymbolValueInterp_Regular) {
dst_is_comdat = lnk_try_comdat_props_from_section_number(dst->u.defined.obj, dst_parsed.section_number, &dst_select, 0, &dst_section_length, &dst_check_sum);
} else if (dst_interp == COFF_SymbolValueInterp_Common) {
dst_select = COFF_ComdatSelect_Largest;
dst_section_length = dst_parsed.value;
dst_check_sum = 0;
dst_is_comdat = 1;
}
// parse src symbol properties
B32 src_is_comdat = 0;
COFF_ComdatSelectType src_select;
U32 src_section_length, src_checks;
U32 src_check_sum;
if (src_interp == COFF_SymbolValueInterp_Regular) {
src_is_comdat = lnk_try_comdat_props_from_section_number(src->u.defined.obj, src_parsed.section_number, &src_select, 0, &src_section_length, &src_check_sum);
} else if (src_interp == COFF_SymbolValueInterp_Common) {
src_select = COFF_ComdatSelect_Largest;
src_section_length = src_parsed.value;
src_check_sum = 0;
src_is_comdat = 1;
}
// regular non-comdat vs communal
if (dst_interp == COFF_SymbolValueInterp_Regular && !dst_is_comdat && src_interp == COFF_SymbolValueInterp_Common) {
}
// abs vs abs
else if (dst_interp == COFF_SymbolValueInterp_Abs && src_interp == COFF_SymbolValueInterp_Abs) {
lnk_error_multiply_defined_symbol(dst, 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->defined.obj->header.is_big_obj);
COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src->defined.obj->header.is_big_obj);
if ((dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias)) {
if (lnk_symbol_defined_is_before(dst, src) || src_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 0;
}
// communal vs regular non-comdat
else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Regular && !src_is_comdat) {
can_replace = 1;
}
// handle COMDATs
else if (dst_is_comdat && src_is_comdat) {
if ((src_select == COFF_ComdatSelect_Any && dst_select == COFF_ComdatSelect_Largest)) {
src_select = COFF_ComdatSelect_Largest;
}
if (src_select == COFF_ComdatSelect_Largest && dst_select == COFF_ComdatSelect_Any) {
dst_select = COFF_ComdatSelect_Largest;
}
if (src_select == dst_select) {
switch (src_select) {
case COFF_ComdatSelect_Null:
case COFF_ComdatSelect_Any: {
if (src_section_length == dst_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
// both COMDATs are valid but to get smaller exe pick smallest
can_replace = src_section_length < dst_section_length;
}
} break;
case COFF_ComdatSelect_NoDuplicates: {
lnk_error_multiply_defined_symbol(dst, src);
} break;
case COFF_ComdatSelect_SameSize: {
if (dst_section_length == src_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} break;
case COFF_ComdatSelect_ExactMatch: {
COFF_SectionHeader *dst_sect_header = lnk_coff_section_header_from_section_number(dst_obj, dst_parsed.section_number);
COFF_SectionHeader *src_sect_header = lnk_coff_section_header_from_section_number(src_obj, src_parsed.section_number);
String8 dst_data = str8_substr(dst_obj->data, rng_1u64(dst_sect_header->foff, dst_sect_header->foff + dst_sect_header->fsize));
String8 src_data = str8_substr(src_obj->data, rng_1u64(src_sect_header->foff, src_sect_header->foff + src_sect_header->fsize));
B32 is_exact_match = 0;
if (dst_check_sum != 0 && src_check_sum != 0) {
is_exact_match = dst_check_sum == src_check_sum && str8_match(dst_data, src_data, 0);
} else {
is_exact_match = str8_match(dst_data, src_data, 0);
}
if (is_exact_match) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} break;
case COFF_ComdatSelect_Largest: {
if (dst_section_length == src_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
can_replace = dst_section_length < src_section_length;
}
} break;
case COFF_ComdatSelect_Associative: { /* ignore */ } break;
default: { InvalidPath; } break;
}
} else {
lnk_error_obj(LNK_Warning_UnresolvedComdat, src_obj,
"%S: COMDAT selection conflict detected, current selection %S, leader selection %S from %S",
src->name, coff_string_from_comdat_select_type(src_select), coff_string_from_comdat_select_type(dst_select), dst_obj);
}
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} else if (dst_ext->characteristics != COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) {
if (lnk_symbol_defined_is_before(src, dst) || dst_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 1;
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} else if (dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) {
lnk_error_multiply_defined_symbol(dst, src);
} else {
can_replace = lnk_symbol_defined_is_before(src, dst);
}
}
// weak vs regular/abs/common
else if (dst_interp == COFF_SymbolValueInterp_Weak && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Abs || src_interp == COFF_SymbolValueInterp_Common)) {
can_replace = 1;
}
// regular/abs/common vs weak
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Abs || dst_interp == COFF_SymbolValueInterp_Common) && src_interp == COFF_SymbolValueInterp_Weak) {
can_replace = 0;
}
// regular/common vs regular/common
else if ((dst_interp == COFF_SymbolValueInterp_Regular || dst_interp == COFF_SymbolValueInterp_Common) && (src_interp == COFF_SymbolValueInterp_Regular || src_interp == COFF_SymbolValueInterp_Common)) {
// parse dst symbol properties
B32 dst_is_comdat = 0;
COFF_ComdatSelectType dst_select;
U32 dst_section_length;
U32 dst_check_sum;
if (dst_interp == COFF_SymbolValueInterp_Regular) {
dst_is_comdat = lnk_try_comdat_props_from_section_number(dst->defined.obj, dst_parsed.section_number, &dst_select, 0, &dst_section_length, &dst_check_sum);
} else if (dst_interp == COFF_SymbolValueInterp_Common) {
dst_select = COFF_ComdatSelect_Largest;
dst_section_length = dst_parsed.value;
dst_check_sum = 0;
dst_is_comdat = 1;
}
// parse src symbol properties
B32 src_is_comdat = 0;
COFF_ComdatSelectType src_select;
U32 src_section_length, src_checks;
U32 src_check_sum;
if (src_interp == COFF_SymbolValueInterp_Regular) {
src_is_comdat = lnk_try_comdat_props_from_section_number(src->defined.obj, src_parsed.section_number, &src_select, 0, &src_section_length, &src_check_sum);
} else if (src_interp == COFF_SymbolValueInterp_Common) {
src_select = COFF_ComdatSelect_Largest;
src_section_length = src_parsed.value;
src_check_sum = 0;
src_is_comdat = 1;
}
// regular non-comdat vs communal
if (dst_interp == COFF_SymbolValueInterp_Regular && !dst_is_comdat && src_interp == COFF_SymbolValueInterp_Common) {
can_replace = 0;
}
// communal vs regular non-comdat
else if (dst_interp == COFF_SymbolValueInterp_Common && src_interp == COFF_SymbolValueInterp_Regular && !src_is_comdat) {
can_replace = 1;
}
// handle COMDATs
else if (dst_is_comdat && src_is_comdat) {
if ((src_select == COFF_ComdatSelect_Any && dst_select == COFF_ComdatSelect_Largest)) {
src_select = COFF_ComdatSelect_Largest;
}
if (src_select == COFF_ComdatSelect_Largest && dst_select == COFF_ComdatSelect_Any) {
dst_select = COFF_ComdatSelect_Largest;
}
if (src_select == dst_select) {
switch (src_select) {
case COFF_ComdatSelect_Null:
case COFF_ComdatSelect_Any: {
if (src_section_length == dst_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
// both COMDATs are valid but to get smaller exe pick smallest
can_replace = src_section_length < dst_section_length;
}
} break;
case COFF_ComdatSelect_NoDuplicates: {
lnk_error_multiply_defined_symbol(dst, src);
} break;
case COFF_ComdatSelect_SameSize: {
if (dst_section_length == src_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} break;
case COFF_ComdatSelect_ExactMatch: {
COFF_SectionHeader *dst_sect_header = lnk_coff_section_header_from_section_number(dst_obj, dst_parsed.section_number);
COFF_SectionHeader *src_sect_header = lnk_coff_section_header_from_section_number(src_obj, src_parsed.section_number);
String8 dst_data = str8_substr(dst_obj->data, rng_1u64(dst_sect_header->foff, dst_sect_header->foff + dst_sect_header->fsize));
String8 src_data = str8_substr(src_obj->data, rng_1u64(src_sect_header->foff, src_sect_header->foff + src_sect_header->fsize));
B32 is_exact_match = 0;
if (dst_check_sum != 0 && src_check_sum != 0) {
is_exact_match = dst_check_sum == src_check_sum && str8_match(dst_data, src_data, 0);
} else {
is_exact_match = str8_match(dst_data, src_data, 0);
}
if (is_exact_match) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
lnk_error_multiply_defined_symbol(dst, src);
}
} break;
case COFF_ComdatSelect_Largest: {
if (dst_section_length == src_section_length) {
can_replace = lnk_obj_is_before(src_obj, dst_obj);
} else {
can_replace = dst_section_length < src_section_length;
}
} break;
case COFF_ComdatSelect_Associative: { /* ignore */ } break;
default: { InvalidPath; } break;
}
} else {
lnk_error_obj(LNK_Warning_UnresolvedComdat, src_obj,
"%S: COMDAT selection conflict detected, current selection %S, leader selection %S from %S",
src->name, coff_string_from_comdat_select_type(src_select), coff_string_from_comdat_select_type(dst_select), dst_obj);
}
} else {
lnk_error(LNK_Error_InvalidPath, "unable to find a suitable replacement logic for symbol combination");
lnk_error_multiply_defined_symbol(dst, src);
}
} break;
case LNK_SymbolScope_Lib: {
can_replace = lnk_symbol_lib_is_before(src, dst);
} break;
default: { InvalidPath; }
} else {
lnk_error(LNK_Error_InvalidPath, "unable to find a suitable replacement logic for symbol combination");
}
return can_replace;
}
internal void
lnk_on_symbol_replace(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src)
{
switch (scope) {
case LNK_SymbolScope_Defined: {
COFF_ParsedSymbol dst_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dst->u.defined.obj, dst->u.defined.symbol_idx);
COFF_SymbolValueInterpType dst_interp = coff_interp_from_parsed_symbol(dst_parsed);
if (dst_interp == COFF_SymbolValueInterp_Regular) {
// remove replaced section from the output
COFF_SectionHeader *dst_sect = lnk_coff_section_header_from_section_number(dst->u.defined.obj, dst_parsed.section_number);
dst_sect->flags |= COFF_SectionFlag_LnkRemove;
COFF_ParsedSymbol dst_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dst->defined.obj, dst->defined.symbol_idx);
COFF_SymbolValueInterpType dst_interp = coff_interp_from_parsed_symbol(dst_parsed);
if (dst_interp == COFF_SymbolValueInterp_Regular) {
// remove replaced section from the output
COFF_SectionHeader *dst_sect = lnk_coff_section_header_from_section_number(dst->defined.obj, dst_parsed.section_number);
dst_sect->flags |= COFF_SectionFlag_LnkRemove;
// remove associated sections from the output
for (U32Node *associated_section = dst->u.defined.obj->associated_sections[dst_parsed.section_number];
associated_section != 0;
associated_section = associated_section->next) {
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(dst->u.defined.obj, associated_section->data);
section_header->flags |= COFF_SectionFlag_LnkRemove;
}
// remove associated sections from the output
for (U32Node *associated_section = dst->defined.obj->associated_sections[dst_parsed.section_number];
associated_section != 0;
associated_section = associated_section->next) {
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(dst->defined.obj, associated_section->data);
section_header->flags |= COFF_SectionFlag_LnkRemove;
}
// assert leader section is live
#if BUILD_DEBUG
{
COFF_ParsedSymbol src_parsed = lnk_parsed_symbol_from_coff_symbol_idx(src->u.defined.obj, src->u.defined.symbol_idx);
COFF_SymbolValueInterpType src_interp = coff_interp_from_parsed_symbol(src_parsed);
if (src_interp == COFF_SymbolValueInterp_Regular) {
COFF_SectionHeader *src_sect = lnk_coff_section_header_from_section_number(src->u.defined.obj, src_parsed.section_number);
AssertAlways(~src_sect->flags & COFF_SectionFlag_LnkRemove);
}
}
#endif
} break;
case LNK_SymbolScope_Lib: {
LNK_Symbol *last;
for (last = src; last->u.member.next != 0; last = last->u.member.next);
last->u.member.next = dst;
} break;
default: { InvalidPath; }
}
// assert leader section is live
#if BUILD_DEBUG
{
COFF_ParsedSymbol src_parsed = lnk_parsed_symbol_from_coff_symbol_idx(src->defined.obj, src->defined.symbol_idx);
COFF_SymbolValueInterpType src_interp = coff_interp_from_parsed_symbol(src_parsed);
if (src_interp == COFF_SymbolValueInterp_Regular) {
COFF_SectionHeader *src_sect = lnk_coff_section_header_from_section_number(src->defined.obj, src_parsed.section_number);
AssertAlways(~src_sect->flags & COFF_SectionFlag_LnkRemove);
}
}
#endif
}
internal void
@@ -407,7 +374,6 @@ lnk_symbol_hash_trie_insert_or_replace(Arena *arena,
LNK_SymbolHashTrieChunkList *chunks,
LNK_SymbolHashTrie **trie,
U64 hash,
LNK_SymbolScope scope,
LNK_Symbol *symbol)
{
LNK_SymbolHashTrie **curr_trie_ptr = trie;
@@ -447,13 +413,13 @@ lnk_symbol_hash_trie_insert_or_replace(Arena *arena,
// apply replacement
if (leader) {
if (lnk_can_replace_symbol(scope, leader, src)) {
if (lnk_can_replace_symbol(leader, src)) {
// discard leader
lnk_on_symbol_replace(scope, leader, src);
lnk_on_symbol_replace(leader, src);
leader = src;
} else {
// discard source
lnk_on_symbol_replace(scope, src, leader);
lnk_on_symbol_replace(src, leader);
src = leader;
}
} else {
@@ -526,7 +492,7 @@ lnk_array_from_symbol_hash_trie_chunk_list(Arena *arena, LNK_SymbolHashTrieChunk
internal COFF_ParsedSymbol
lnk_parsed_symbol_from_defined(LNK_Symbol *symbol)
{
return lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, symbol->u.defined.symbol_idx);
return lnk_parsed_symbol_from_coff_symbol_idx(symbol->defined.obj, symbol->defined.symbol_idx);
}
internal COFF_SymbolValueInterpType
@@ -576,11 +542,11 @@ lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_SymbolDefined symbol)
SLLQueuePush(sf, sl, s);
// does weak symbol have a definition?
LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, current_parsed.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn_symbol->u.defined.obj, defn_symbol->u.defined.symbol_idx);
LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, current_parsed.name);
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_coff_symbol_idx(defn_symbol->defined.obj, defn_symbol->defined.symbol_idx);
COFF_SymbolValueInterpType defn_interp = coff_interp_symbol(defn_parsed.section_number, defn_parsed.value, defn_parsed.storage_class);
if (defn_interp != COFF_SymbolValueInterp_Weak) {
current_symbol = defn_symbol->u.defined;
current_symbol = defn_symbol->defined;
break;
}
@@ -593,20 +559,20 @@ lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_SymbolDefined symbol)
if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
if (tag_interp == COFF_SymbolValueInterp_Undefined || tag_interp == COFF_SymbolValueInterp_Weak) {
LNK_Symbol *dep_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, tag_parsed.name);
LNK_Symbol *dep_symbol = lnk_symbol_table_search(symtab, tag_parsed.name);
tag_interp = lnk_interp_from_symbol(dep_symbol);
}
if (tag_interp == COFF_SymbolValueInterp_Weak) { goto exit; }
}
} else if (current_interp == COFF_SymbolValueInterp_Undefined) {
LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, current_parsed.name);
LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, current_parsed.name);
COFF_SymbolValueInterpType defn_interp = lnk_interp_from_symbol(defn_symbol);
// unresolved undefined symbol
if (defn_interp == COFF_SymbolValueInterp_Undefined) { break; }
// follow symbol definition
current_symbol = defn_symbol->u.defined;
current_symbol = defn_symbol->defined;
} else { break; }
}
@@ -630,41 +596,39 @@ lnk_symbol_table_init(TP_Arena *arena)
{
LNK_SymbolTable *symtab = push_array(arena->v[0], LNK_SymbolTable, 1);
symtab->arena = arena;
for (U64 i = 0; i < LNK_SymbolScope_Count; ++i) {
symtab->chunk_lists[i] = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count);
}
symtab->chunks = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count);
return symtab;
}
internal void
lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_SymbolScope scope, LNK_Symbol *symbol)
lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, U64 worker_id, LNK_Symbol *symbol)
{
U64 hash = lnk_symbol_hash(symbol->name);
lnk_symbol_hash_trie_insert_or_replace(arena, &symtab->chunk_lists[scope][worker_id], &symtab->scopes[scope], hash, scope, symbol);
lnk_symbol_hash_trie_insert_or_replace(arena, &symtab->chunks[worker_id], &symtab->root, hash, symbol);
}
internal void
lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_SymbolScope scope, LNK_Symbol *symbol)
lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol)
{
lnk_symbol_table_push_(symtab, symtab->arena->v[0], 0, scope, symbol);
lnk_symbol_table_push_(symtab, symtab->arena->v[0], 0, symbol);
}
internal LNK_SymbolHashTrie *
lnk_symbol_table_search_(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name)
lnk_symbol_table_search_(LNK_SymbolTable *symtab, String8 name)
{
U64 hash = lnk_symbol_hash(name);
return lnk_symbol_hash_trie_search(symtab->scopes[scope], hash, name);
return lnk_symbol_hash_trie_search(symtab->root, hash, name);
}
internal LNK_Symbol *
lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name)
lnk_symbol_table_search(LNK_SymbolTable *symtab, String8 name)
{
LNK_SymbolHashTrie *trie = lnk_symbol_table_search_(symtab, scope, name);
LNK_SymbolHashTrie *trie = lnk_symbol_table_search_(symtab, name);
return trie ? trie->symbol : 0;
}
internal LNK_Symbol *
lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *fmt, ...)
lnk_symbol_table_searchf(LNK_SymbolTable *symtab, char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
@@ -672,7 +636,7 @@ lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *f
String8 name = push_str8fv(scratch.arena, fmt, args);
va_end(args);
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, scope, name);
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, name);
scratch_end(scratch);
return symbol;
@@ -681,7 +645,7 @@ lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *f
internal ISectOff
lnk_sc_from_symbol(LNK_Symbol *symbol)
{
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, symbol->u.defined.symbol_idx);
COFF_ParsedSymbol parsed_symbol = lnk_parsed_symbol_from_coff_symbol_idx(symbol->defined.obj, symbol->defined.symbol_idx);
ISectOff sc = {0};
sc.isect = parsed_symbol.section_number;
+8 -28
View File
@@ -5,35 +5,16 @@
// --- Symbol ------------------------------------------------------------------
typedef enum
{
LNK_SymbolScope_Defined,
LNK_SymbolScope_Lib,
LNK_SymbolScope_Count
} LNK_SymbolScope;
typedef struct LNK_SymbolDefined
{
struct LNK_Obj *obj;
U32 symbol_idx;
} LNK_SymbolDefined;
typedef struct LNK_SymbolLib
{
struct LNK_Lib *lib;
U32 member_idx;
} LNK_SymbolLib;
typedef struct LNK_Symbol
{
String8 name;
union {
LNK_SymbolDefined defined;
struct {
struct LNK_Symbol *next;
LNK_SymbolLib v;
} member;
} u;
String8 name;
LNK_SymbolDefined defined;
} LNK_Symbol;
// --- Symbol Containers -------------------------------------------------------
@@ -92,14 +73,13 @@ typedef struct LNK_SymbolHashTrieChunkList
typedef struct LNK_SymbolTable
{
TP_Arena *arena;
LNK_SymbolHashTrie *scopes[LNK_SymbolScope_Count];
LNK_SymbolHashTrieChunkList *chunk_lists[LNK_SymbolScope_Count];
LNK_SymbolHashTrie *root;
LNK_SymbolHashTrieChunkList *chunks;
} LNK_SymbolTable;
// --- Symbol Make -------------------------------------------------------------
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, U32 member_idx);
// --- Symbol Containers ------------------------------------------------------
@@ -113,7 +93,7 @@ internal LNK_SymbolArray lnk_symbol_array_from_list(Arena *arena, LNK_Symbol
// --- Symbol Hash Trie --------------------------------------------------------
internal void lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunks, LNK_SymbolHashTrie **trie, U64 hash, LNK_SymbolScope scope, LNK_Symbol *symbol);
internal void lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunks, LNK_SymbolHashTrie **trie, U64 hash, LNK_Symbol *symbol);
internal LNK_SymbolHashTrie * lnk_symbol_hash_trie_search(LNK_SymbolHashTrie *trie, U64 hash, String8 name);
internal void lnk_symbol_hash_trie_remove(LNK_SymbolHashTrie *trie);
internal LNK_SymbolHashTrieChunk ** lnk_array_from_symbol_hash_trie_chunk_list(Arena *arena, LNK_SymbolHashTrieChunkList *lists, U64 lists_count, U64 *count_out);
@@ -129,9 +109,9 @@ internal LNK_SymbolDefined lnk_resolve_weak_symbol(LNK_SymbolTable *sym
internal U64 lnk_symbol_hash(String8 string);
internal LNK_SymbolTable * lnk_symbol_table_init(TP_Arena *arena);
internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_SymbolScope scope, LNK_Symbol *symbol);
internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name);
internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *fmt, ...);
internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol);
internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, String8 name);
internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, char *fmt, ...);
// --- Symbol Contrib Helpers --------------------------------------------------