assign COMDAT symlinks as soon as the symbol table is processed

This commit is contained in:
Nikita Smith
2025-08-01 11:41:20 -07:00
committed by Ryan Fleury
parent 1fe85acff8
commit dd715dacf7
5 changed files with 74 additions and 81 deletions
+13 -30
View File
@@ -1021,10 +1021,6 @@ THREAD_POOL_TASK_FUNC(lnk_undef_symbol_finder)
for (U64 symbol_idx = range.min; symbol_idx < range.max; symbol_idx += 1) {
LNK_SymbolNode *symbol_n = task->lookup_node_arr.v[symbol_idx];
LNK_Symbol *symbol = symbol_n->data;
if (str8_match(symbol->name, str8_lit("return_1"), 0)) {
int x = 0;
}
LNK_Symbol *has_defn = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol->name);
if (has_defn) {
@@ -2110,15 +2106,14 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
}
internal B32
lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_Symbol **symlinks, LNK_SymbolDefined symbol, LNK_SymbolDefined *symbol_out)
lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_SymbolDefined symbol, LNK_SymbolDefined *symbol_out)
{
B32 is_resolved = 1;
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx(symbol.obj, symbol.symbol_idx);
COFF_SymbolValueInterpType symbol_interp = coff_interp_symbol(symbol_parsed.section_number, symbol_parsed.value, symbol_parsed.storage_class);
switch (symbol_interp) {
case COFF_SymbolValueInterp_Regular: {
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(symbol.obj, symbol_parsed.section_number);
LNK_Symbol *symlink = section_header->flags & COFF_SectionFlag_LnkCOMDAT ? symlinks[symbol_parsed.section_number] : 0;
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(symbol.obj, symbol_parsed.section_number);
*symbol_out = symlink ? symlink->u.defined : symbol;
} break;
case COFF_SymbolValueInterp_Weak: {
@@ -2157,12 +2152,7 @@ lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_Symbol **symlinks, LNK_SymbolDef
}
internal void
lnk_gc_comdats(TP_Context *tp,
LNK_SymbolTable *symtab,
U64 objs_count,
LNK_Obj **objs,
LNK_Symbol ***symlinks,
LNK_Config *config)
lnk_gc_comdats(TP_Context *tp, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs, LNK_Config *config)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0,0);
@@ -2252,7 +2242,7 @@ lnk_gc_comdats(TP_Context *tp,
for EachIndex(reloc_idx, t->relocs.count) {
COFF_Reloc *reloc = &t->relocs.v[reloc_idx];
LNK_SymbolDefined reloc_symbol = {0};
B32 is_reloc_symbol_resolved = lnk_resolve_symbol(symtab, symlinks[t->obj->input_idx], (LNK_SymbolDefined){ .obj = t->obj, .symbol_idx = reloc->isymbol }, &reloc_symbol);
B32 is_reloc_symbol_resolved = lnk_resolve_symbol(symtab, (LNK_SymbolDefined){ .obj = t->obj, .symbol_idx = reloc->isymbol }, &reloc_symbol);
if (is_reloc_symbol_resolved) {
// parse and interp reloc symbol
LNK_Obj *reloc_obj = reloc_symbol.obj;
@@ -2452,7 +2442,7 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
if (~section_header->flags & COFF_SectionFlag_LnkCOMDAT) { continue; }
LNK_Symbol *symlink = task->symlinks[obj_idx][section_number];
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(obj, section_number);
if (symlink == 0) { continue; }
COFF_ParsedSymbol symlink_parsed = lnk_parsed_symbol_from_defined(symlink);
@@ -2479,7 +2469,7 @@ 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 = task->symlinks[obj_idx][symbol.section_number];
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(obj, symbol.section_number);
if (symlink && symlink->u.defined.obj != obj) {
U32 section_number;
U32 value;
@@ -2667,7 +2657,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task)
}
internal void
lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Symbol **symlinks, LNK_Obj *obj, B8 *was_symbol_patched, COFF_SymbolValueInterpType fixup_type)
lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Obj *obj, B8 *was_symbol_patched, COFF_SymbolValueInterpType fixup_type)
{
ProfBeginV("%S\n", obj->path);
@@ -2681,7 +2671,7 @@ lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Symbol **symlinks, LNK_Obj *ob
LNK_SymbolDefined symbol_to_resolve = { .obj = obj, .symbol_idx = symbol_idx };
LNK_SymbolDefined fixup_symbol = {0};
B32 is_resolved = lnk_resolve_symbol(symtab, symlinks, symbol_to_resolve, &fixup_symbol);
B32 is_resolved = lnk_resolve_symbol(symtab, symbol_to_resolve, &fixup_symbol);
if (is_resolved) {
COFF_ParsedSymbol fixup_src = lnk_parsed_symbol_from_coff_symbol_idx(fixup_symbol.obj, fixup_symbol.symbol_idx);
COFF_SymbolValueInterpType fixup_type = coff_interp_symbol(fixup_src.section_number, fixup_src.value, fixup_src.storage_class);
@@ -2714,28 +2704,28 @@ internal
THREAD_POOL_TASK_FUNC(lnk_patch_common_symbols_task)
{
LNK_BuildImageTask *task = raw_task;
lnk_patch_obj_symtab(task->symtab, task->symlinks[task_id], task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Common);
lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Common);
}
internal
THREAD_POOL_TASK_FUNC(lnk_patch_abs_symbols_task)
{
LNK_BuildImageTask *task = raw_task;
lnk_patch_obj_symtab(task->symtab, task->symlinks[task_id], task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Abs);
lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Abs);
}
internal
THREAD_POOL_TASK_FUNC(lnk_patch_undefined_symbols_task)
{
LNK_BuildImageTask *task = raw_task;
lnk_patch_obj_symtab(task->symtab, task->symlinks[task_id], task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Undefined);
lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Undefined);
}
internal
THREAD_POOL_TASK_FUNC(lnk_patch_weak_symbols_task)
{
LNK_BuildImageTask *task = raw_task;
lnk_patch_obj_symtab(task->symtab, task->symlinks[task_id], task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Weak);
lnk_patch_obj_symtab(task->symtab, task->objs[task_id], task->u.patch_symtabs.was_symbol_patched[task_id], COFF_SymbolValueInterp_Weak);
}
internal U64
@@ -3849,17 +3839,11 @@ lnk_build_image(TP_Arena *arena,
Temp scratch = scratch_begin(arena->v, arena->count);
//
// gather symbol links to COMDAT sections
//
LNK_Symbol ***symlinks = push_array(arena->v[0], LNK_Symbol **, objs_count);
for EachIndex(obj_idx, objs_count) { symlinks[obj_idx] = lnk_symlinks_from_obj(scratch.arena, symtab, objs[obj_idx]); }
//
// remove unreachable COMDAT sections
//
if (config->opt_ref == LNK_SwitchState_Yes) {
lnk_gc_comdats(tp, symtab, objs_count, objs, symlinks, config);
lnk_gc_comdats(tp, symtab, objs_count, objs, config);
}
//
@@ -3880,7 +3864,6 @@ lnk_build_image(TP_Arena *arena,
.function_pad_min = config->function_pad_min,
.default_align = coff_default_align_from_machine(config->machine),
.null_sc = push_array(arena->v[0], LNK_SectionContrib, 1),
.symlinks = symlinks,
};
{
-1
View File
@@ -81,7 +81,6 @@ typedef struct
U64 function_pad_min;
U64 default_align;
LNK_SectionContrib *null_sc;
LNK_Symbol ***symlinks;
LNK_SectionContrib ***sect_map;
HashTable *contribs_ht;
LNK_SectionArray image_sects;
+38 -35
View File
@@ -346,24 +346,11 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
LNK_InputCoffSymbolTable *task = raw_task;
LNK_Obj *obj = &task->objs.v[task_id].data;
//
// parse obj header
//
COFF_FileHeaderInfo header = coff_file_header_info_from_data(obj->data);
//
// extract COFF info
//
String8 raw_coff_section_table = str8_substr(obj->data, header.section_table_range);
String8 raw_coff_symbol_table = str8_substr(obj->data, header.symbol_table_range);
String8 raw_coff_string_table = str8_substr(obj->data, header.string_table_range);
COFF_ParsedSymbol symbol = {0};
for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
// read symbol
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
switch (interp) {
case COFF_SymbolValueInterp_Regular: {
if (symbol.storage_class == COFF_SymStorageClass_External) {
@@ -411,6 +398,34 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
}
}
internal LNK_SymbolHashTrie **
lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj)
{
LNK_SymbolHashTrie **symlinks = push_array(arena, LNK_SymbolHashTrie *, obj->header.section_count_no_null+1);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular && symbol.aux_symbol_count == 0 && symbol.storage_class == COFF_SymStorageClass_External) {
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);
}
}
}
}
return symlinks;
}
internal
THREAD_POOL_TASK_FUNC(lnk_assign_comdat_symlinks_task)
{
LNK_InputCoffSymbolTable *task = raw_task;
LNK_Obj *obj = &task->objs.v[task_id].data;
obj->symlinks = lnk_symlinks_from_obj(arena, task->symtab, obj);
}
internal LNK_SymbolInputResult
lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs)
{
@@ -423,6 +438,7 @@ lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab,
task.weak_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count);
task.undef_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count);
tp_for_parallel(tp, arena, objs.count, lnk_input_coff_symbol_table, &task);
tp_for_parallel(tp, arena, objs.count, lnk_assign_comdat_symlinks_task, &task);
LNK_SymbolInputResult result = {0};
SLLConcatInPlaceArray(&result.weak_symbols, task.weak_lists, tp->worker_count);
@@ -499,6 +515,13 @@ lnk_obj_get_removed_section_number(LNK_Obj *obj)
return obj->header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16;
}
internal LNK_Symbol *
lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number)
{
LNK_SymbolHashTrie *symlink = obj->symlinks[section_number];
return symlink ? symlink->symbol : 0;
}
internal COFF_SectionHeader *
lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number)
{
@@ -513,26 +536,6 @@ lnk_coff_section_table_from_obj(LNK_Obj *obj)
return (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str;
}
internal LNK_Symbol **
lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj)
{
LNK_Symbol **symlinks = push_array(arena, LNK_Symbol *, obj->header.section_count_no_null+1);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular && symbol.aux_symbol_count == 0 && symbol.storage_class == COFF_SymStorageClass_External) {
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);
}
}
}
}
return symlinks;
}
internal COFF_RelocArray
lnk_coff_reloc_info_from_section_number(LNK_Obj *obj, U64 section_number)
{
+15 -13
View File
@@ -7,14 +7,15 @@
typedef struct LNK_Obj
{
String8 data;
String8 path;
struct LNK_Lib *lib;
U32 input_idx;
COFF_FileHeaderInfo header;
U32 *comdats;
B8 hotpatch;
U32Node **associated_sections;
String8 data;
String8 path;
struct LNK_Lib *lib;
U32 input_idx;
COFF_FileHeaderInfo header;
U32 *comdats;
B8 hotpatch;
U32Node **associated_sections;
LNK_SymbolHashTrie **symlinks;
} LNK_Obj;
typedef struct LNK_ObjNode
@@ -101,11 +102,12 @@ internal LNK_SymbolInputResult lnk_input_obj_symbols(TP_Context *tp, TP_Arena *a
// --- Metadata ----------------------------------------------------------------
internal U32 lnk_obj_get_features(LNK_Obj *obj);
internal U32 lnk_obj_get_comp_id(LNK_Obj *obj);
internal U32 lnk_obj_get_vol_md(LNK_Obj *obj);
internal String8 lnk_obj_get_lib_path(LNK_Obj *obj);
internal U32 lnk_obj_get_removed_section_number(LNK_Obj *obj);
internal U32 lnk_obj_get_features(LNK_Obj *obj);
internal U32 lnk_obj_get_comp_id(LNK_Obj *obj);
internal U32 lnk_obj_get_vol_md(LNK_Obj *obj);
internal String8 lnk_obj_get_lib_path(LNK_Obj *obj);
internal U32 lnk_obj_get_removed_section_number(LNK_Obj *obj);
internal LNK_Symbol * lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number);
// --- Symbol & Section Helpers ------------------------------------------------
+8 -2
View File
@@ -489,11 +489,17 @@ lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_SymbolScope scope, LNK_Symbol
lnk_symbol_table_push_(symtab, symtab->arena->v[0], 0, scope, symbol);
}
internal LNK_SymbolHashTrie *
lnk_symbol_table_search_(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name)
{
U64 hash = lnk_symbol_hash(name);
return lnk_symbol_hash_trie_search(symtab->scopes[scope], hash, name);
}
internal LNK_Symbol *
lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name)
{
U64 hash = lnk_symbol_hash(name);
LNK_SymbolHashTrie *trie = lnk_symbol_hash_trie_search(symtab->scopes[scope], hash, name);
LNK_SymbolHashTrie *trie = lnk_symbol_table_search_(symtab, scope, name);
return trie ? trie->symbol : 0;
}