WIP collect sections associations

This commit is contained in:
Nikita Smith
2025-07-16 15:37:52 -07:00
committed by Ryan Fleury
parent a4ac07162e
commit a6b2cf64ba
7 changed files with 107 additions and 47 deletions
+2 -1
View File
@@ -348,7 +348,8 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
#endif
#define PtrFromInt(i) (void*)(i)
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b))
#define Compose32Bit(a,b) ((((U32)a) << 16) | ((U32)b))
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1))
+1 -1
View File
@@ -296,7 +296,7 @@ coff_parse_secdef(COFF_ParsedSymbol symbol, B32 is_big_obj, COFF_ComdatSelectTyp
if (selection_out) *selection_out = sd->selection;
if (length_out) *length_out = sd->length;
if (check_sum_out) *check_sum_out = sd->check_sum;
if (number_out) *number_out = sd->number_lo | ((U32)sd->number_hi << 16);
if (number_out) *number_out = Compose32Bit(sd->number_hi, sd->number_lo);
} else {
COFF_SymbolSecDef *sd = (COFF_SymbolSecDef *)((COFF_Symbol16 *)symbol.raw_symbol + 1);
if (selection_out) *selection_out = sd->selection;
+6
View File
@@ -3,6 +3,12 @@
#pragma once
typedef struct U32Node
{
struct U32Node *next;
U32 data;
} U32Node;
typedef struct U64Node
{
struct U64Node *next;
-2
View File
@@ -4053,8 +4053,6 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
.null_sc = push_array(arena->v[0], LNK_SectionContrib, 1),
};
tp_for_parallel(tp, 0, objs_count, lnk_remove_associative_sections_task, &task);
{
ProfBegin("Define And Count Sections");
TP_Temp temp = tp_temp_begin(arena);
+35 -9
View File
@@ -224,6 +224,31 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
scratch_end(scratch);
}
//
// collect sections associations
//
U32Node **associated_sections = push_array(arena, U32Node *, header.section_count_no_null + 1);
{
String8 string_table = str8_substr(input->data, header.string_table_range);
String8 symbol_table = str8_substr(input->data, header.symbol_table_range);
COFF_ParsedSymbol symbol;
for (U32 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = coff_parse_symbol(header, string_table, symbol_table, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
if (interp == COFF_SymbolValueInterp_Regular && symbol.storage_class == COFF_SymStorageClass_Static && symbol.aux_symbol_count > 0) {
COFF_ComdatSelectType selection = COFF_ComdatSelect_Null;
U32 section_number = 0;
coff_parse_secdef(symbol, header.is_big_obj, &selection, &section_number, 0, 0);
if (selection != COFF_ComdatSelect_Associative) { continue; }
U32Node *associated_node = push_array(arena, U32Node, 1);
associated_node->data = symbol.section_number;
SLLStackPush(associated_sections[section_number], associated_node);
}
}
}
//
// extract obj features from compile symbol in .debug$S
@@ -267,13 +292,14 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
}
// fill out obj
obj->data = input->data;
obj->path = push_str8_copy(arena, input->path);
obj->lib_path = push_str8_copy(arena, input->lib_path);
obj->input_idx = obj_idx;
obj->header = header;
obj->comdats = comdats;
obj->hotpatch = hotpatch;
obj->data = input->data;
obj->path = push_str8_copy(arena, input->path);
obj->lib_path = push_str8_copy(arena, input->lib_path);
obj->input_idx = obj_idx;
obj->header = header;
obj->comdats = comdats;
obj->hotpatch = hotpatch;
obj->associated_sections = associated_sections;
ProfEnd();
}
@@ -466,13 +492,13 @@ lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number)
}
internal B32
lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_length_out, U32 *check_sum_out)
lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out)
{
Assert(section_number > 0);
U32 symbol_idx = obj->comdats[section_number-1];
if (symbol_idx != max_U32) {
COFF_ParsedSymbol secdef = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
coff_parse_secdef(secdef, obj->header.is_big_obj, select_out, 0, section_length_out, check_sum_out);
coff_parse_secdef(secdef, obj->header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out);
return 1;
}
return 0;
+2 -1
View File
@@ -14,6 +14,7 @@ typedef struct LNK_Obj
COFF_FileHeaderInfo header;
U32 *comdats;
B8 hotpatch;
U32Node **associated_sections;
} LNK_Obj;
typedef struct LNK_ObjNode
@@ -109,7 +110,7 @@ internal U32 lnk_obj_get_vol_md(LNK_Obj *obj);
internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff(LNK_Obj *obj, void *coff_symbol);
internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx);
internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number);
internal B32 lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_length_out, U32 *check_sum_out);
internal B32 lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out);
internal B32 lnk_is_coff_section_debug(LNK_Obj *obj, U64 sect_idx);
// --- Helpers -----------------------------------------------------------------
+61 -33
View File
@@ -193,7 +193,7 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
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, &dst_section_length, &dst_check_sum);
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;
@@ -207,7 +207,7 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
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, &src_section_length, &src_check_sum);
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;
@@ -308,23 +308,44 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
internal void
lnk_on_symbol_replace(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
{
Assert(dst != src);
if (scope == LNK_SymbolScope_Lib) {
dst->u.lib = src->u.lib;
} else if (scope == LNK_SymbolScope_Defined) {
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_symbol(dst_parsed.section_number, dst_parsed.value, dst_parsed.storage_class);
COFF_SymbolValueInterpType src_interp = coff_interp_symbol(src_parsed.section_number, src_parsed.value, src_parsed.storage_class);
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;
dst->u.defined = src->u.defined;
// 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;
}
}
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);
// make sure leader section is not removed from the output
#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_Import: {
// illegal to replace imports
InvalidPath;
} break;
case LNK_SymbolScope_Lib: {
// nothing to replace
} break;
default: { InvalidPath; }
}
}
@@ -551,31 +572,38 @@ THREAD_POOL_TASK_FUNC(lnk_finalize_weak_symbols_task)
break;
}
// record visited symbol
struct LookupLocation *loc = push_array(scratch.arena, struct LookupLocation, 1);
loc->symbol = current_symbol;
SLLQueuePush(lookup_first, lookup_last, loc);
COFF_ParsedSymbol current_parsed = lnk_parsed_symbol_from_coff_symbol_idx(current_symbol.obj, current_symbol.symbol_idx);
COFF_SymbolValueInterpType current_interp = coff_interp_symbol(current_parsed.section_number, current_parsed.value, current_parsed.storage_class);
if (current_interp != COFF_SymbolValueInterp_Weak && current_interp != COFF_SymbolValueInterp_Undefined) {
break;
}
if (current_interp == COFF_SymbolValueInterp_Weak) {
// record visited symbol
struct LookupLocation *loc = push_array(scratch.arena, struct LookupLocation, 1);
loc->symbol = current_symbol;
SLLQueuePush(lookup_first, lookup_last, loc);
// does weak symbol have the strong 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);
COFF_SymbolValueInterpType defn_interp = coff_interp_symbol(defn_parsed.section_number, defn_parsed.value, defn_parsed.storage_class);
if (defn_interp != COFF_SymbolValueInterp_Weak) {
// 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);
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;
break;
}
// no definition fallback to the tag
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->header.is_big_obj);
COFF_ParsedSymbol tag_parsed = lnk_parsed_symbol_from_coff_symbol_idx(current_symbol.obj, weak_ext->tag_index);
COFF_SymbolValueInterpType tag_interp = coff_interp_symbol(tag_parsed.section_number, tag_parsed.value, tag_parsed.storage_class);
current_symbol = (LNK_SymbolDefined){ .obj = current_symbol.obj, .symbol_idx = weak_ext->tag_index };
} else if (current_interp == COFF_SymbolValueInterp_Undefined) {
LNK_Symbol *defn_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, current_parsed.name);
if (defn_symbol == 0) {
MemoryZeroStruct(&current_symbol);
break;
}
current_symbol = defn_symbol->u.defined;
} else {
break;
}
// no strong definition fallback to the tag
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->header.is_big_obj);
COFF_ParsedSymbol tag_parsed = lnk_parsed_symbol_from_coff_symbol_idx(current_symbol.obj, weak_ext->tag_index);
COFF_SymbolValueInterpType tag_interp = coff_interp_symbol(tag_parsed.section_number, tag_parsed.value, tag_parsed.storage_class);
current_symbol = (LNK_SymbolDefined){ .obj = current_symbol.obj, .symbol_idx = weak_ext->tag_index };
}
// replace weak symbol with it's tag