add replacement cases for weak vs. undefined and vice versa

This commit is contained in:
Nikita Smith
2025-08-18 15:36:55 -07:00
parent 873aa475e8
commit 31b2b1c0f7
+44 -5
View File
@@ -145,9 +145,30 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Regular) {
can_replace = 1;
}
// undefined vs weak
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Weak) {
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;
}
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(weak, undef);
} 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 undefined
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
@@ -165,7 +186,7 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
else if (dst_interp == COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Debug) {
can_replace = 1;
}
// regular/weak/common/abs/debug vs undefined
// regular/common/abs/debug vs undefined
else if (dst_interp != COFF_SymbolValueInterp_Undefined && src_interp == COFF_SymbolValueInterp_Undefined) {
can_replace = 0;
}
@@ -197,7 +218,25 @@ lnk_can_replace_symbol(LNK_SymbolScope scope, LNK_Symbol *dst, LNK_Symbol *src)
}
// weak vs weak
else if (dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Weak) {
can_replace = lnk_symbol_defined_is_before(src, dst);
COFF_ParsedSymbol dst_parsed = lnk_parsed_symbol_from_defined(dst);
COFF_ParsedSymbol src_parsed = lnk_parsed_symbol_from_defined(src);
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) {
// TODO: test
lnk_error_multiply_defined_symbol(dst, src);
} else if (dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias) {
// TODO: test
can_replace = 0;
} else if (dst_ext->characteristics != COFF_WeakExt_SearchAlias && src_ext->characteristics == COFF_WeakExt_SearchAlias) {
// TODO: test
can_replace = 1;
} else if (dst_ext->characteristics == COFF_WeakExt_NoLibrary && src_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 1;
can_replace = lnk_symbol_defined_is_before(src, dst);
} 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)) {