prevent dropping of newly inserted symbol while selecting slot leader

This commit is contained in:
Nikita Smith
2025-06-25 10:53:23 -07:00
committed by Ryan Fleury
parent 3eb7debad5
commit aafb980c6b
+20 -14
View File
@@ -287,12 +287,16 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path); lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path);
} break; } break;
case COFF_ComdatSelect_SameSize: { case COFF_ComdatSelect_SameSize: {
if (dst_section_length != src_section_length) { if (dst_section_length == src_section_length) {
can_replace = src_obj->input_idx < dst_obj->input_idx;
} else {
lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path); lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path);
} }
} break; } break;
case COFF_ComdatSelect_ExactMatch: { case COFF_ComdatSelect_ExactMatch: {
if (dst_check_sum != src_check_sum) { if (dst_check_sum == src_check_sum) {
can_replace = src_obj->input_idx < dst_obj->input_idx;
} else {
lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path); lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src_obj, "multiply defined symbol %S in %S", dst->name, dst_obj->path);
} }
} break; } break;
@@ -398,26 +402,28 @@ lnk_symbol_hash_trie_insert_or_replace(Arena *arena,
if (curr_name && str8_match(*curr_name, symbol->name, 0)) { if (curr_name && str8_match(*curr_name, symbol->name, 0)) {
for (LNK_Symbol *src = symbol;;) { for (LNK_Symbol *src = symbol;;) {
// try replacing current symbol with zero, otherwise loop back and retry // try replacing current symbol with zero, otherwise loop back and retry
LNK_Symbol *dst = ins_atomic_ptr_eval_assign(&curr_trie->symbol, 0); LNK_Symbol *leader = ins_atomic_ptr_eval_assign(&curr_trie->symbol, 0);
// apply replacement logic // apply replacement
LNK_Symbol *current_symbol = dst; if (leader) {
if (dst) { if (lnk_can_replace_symbol(leader, src)) {
if (lnk_can_replace_symbol(dst, src)) { // discard leader
// HACK: patch dst because relocations might point to it lnk_on_symbol_replace(leader, src);
lnk_on_symbol_replace(dst, src); leader = src;
current_symbol = src;
} else { } else {
// discard source // discard source
lnk_on_symbol_replace(src, dst); lnk_on_symbol_replace(src, leader);
src = leader;
} }
} else {
leader = src;
} }
// try replacing symbol, if another thread has already taken the slot, rerun the whole loop // try replacing symbol, if another thread has already taken the slot, rerun replacement loop again
dst = ins_atomic_ptr_eval_cond_assign(&curr_trie->symbol, current_symbol, 0); LNK_Symbol *was_replaced = ins_atomic_ptr_eval_cond_assign(&curr_trie->symbol, leader, 0);
// symbol replaced, exit // symbol replaced, exit
if (dst == 0) { if (was_replaced == 0) {
goto exit; goto exit;
} }
} }