commit 14e3792d88237772be6076f14a77103d5ea746f8
parent 769d6ae1ab02a5531923e468ed1a64d69cc3456d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 5 Jun 2026 14:47:44 -0700
modularity: gate COFF weak-extern underscore alias on a vtable capability + fix stale objdump golden
- src/link/link_resolve.c: the mingw single-underscore weak-external alias recovery now gates on a
new ObjFormatImpl.weak_extern_underscore_alias (COFF=1) via obj_format_weak_extern_underscore_alias(),
replacing the last identity switch in generic link code. The PE-specific
de/re-underscore mechanism stays, but only formats that declare the capability run it. Provably
equivalent (1 for COFF, 0 elsewhere).
- test/objdump/aarch64/cases/04-disasm-stripped-segment.expected: refresh the stale golden to the
disassembler's canonical alias output (sxtw x8, w9) for bytes 28 7d 40 93; sbfm xd,xn,#0,#31 IS SXTW,
matching binutils/LLVM. (Was failing identically on baseline 30367860 — a pre-existing stale golden,
not a regression.)
test-driver-objdump 14/0 (was 13/1); test-link 122/0, elf 41/0, ar 20/20, smoke x64+rv64 green.
Diffstat:
6 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/link/link_resolve.c b/src/link/link_resolve.c
@@ -405,7 +405,7 @@ void link_resolve_undefs(Linker* l, LinkImage* img) {
* because the alias relationship is purely a naming convention in
* the mingw CRT — losing the aux TagIndex means we can't tell
* which side is the alias declarator. */
- if (l->c->target.obj == KIT_OBJ_COFF && s->name != 0) {
+ if (obj_format_weak_extern_underscore_alias(l->c) && s->name != 0) {
Slice nm_s = pool_slice(l->c->global, s->name);
const char* nm = nm_s.s;
size_t nlen = nm_s.len;
diff --git a/src/obj/format.h b/src/obj/format.h
@@ -176,6 +176,11 @@ typedef struct ObjFormatImpl {
* Mach-O=1; COFF (Windows TEB model) and Wasm have no such representation,
* =0. Read by obj_format_supports_symbol_feature. */
u8 tls_symbol_features;
+ /* Resolves weak-external / undefined references via the mingw single-
+ * underscore alias convention (e.g. `__set_app_type` <-> `_set_app_type`)
+ * during link symbol resolution: COFF=1, else 0. Read by
+ * obj_format_weak_extern_underscore_alias. */
+ u8 weak_extern_underscore_alias;
/* ---- C-source backend (c_target) emission spellings ----
*
diff --git a/src/obj/obj.h b/src/obj/obj.h
@@ -805,6 +805,12 @@ int obj_format_supports_symbol_feature(const Compiler*, int symfeat);
* ELF / Mach-O no (they pull only for strong undefs). */
int obj_format_weak_undef_pulls_archive_member(const Compiler*);
+/* True when the active object format recovers weak-external / undefined
+ * references via the mingw single-underscore alias convention (e.g.
+ * `__set_app_type` <-> `_set_app_type`) during link symbol resolution.
+ * COFF yes, ELF / Mach-O / Wasm no. */
+int obj_format_weak_extern_underscore_alias(const Compiler*);
+
/* True when static-IFUNC resolution on the active target goes through a
* `[__rela_iplt_start, __rela_iplt_end)` table of R_*_IRELATIVE relocs
* (walked by FreeBSD's crt before main) rather than kit's ctor-based
diff --git a/src/obj/obj_secnames.c b/src/obj/obj_secnames.c
@@ -345,6 +345,11 @@ int obj_format_weak_undef_pulls_archive_member(const Compiler* c) {
return fmt && fmt->weak_undef_pulls_archive_member;
}
+int obj_format_weak_extern_underscore_alias(const Compiler* c) {
+ const ObjFormatImpl* fmt = c ? obj_format_lookup(c->target.obj) : NULL;
+ return fmt && fmt->weak_extern_underscore_alias;
+}
+
int obj_format_supports_symbol_feature(const Compiler* c, int symfeat) {
/* The only format-divergent feature axis today is TLS access: only ELF and
* Mach-O can represent the ELF/Mach-O TLS-access features the CG layer mints.
diff --git a/src/obj/registry.c b/src/obj/registry.c
@@ -404,6 +404,7 @@ static const ObjFormatImpl obj_format_impl_coff = {
.tls_symbol_features = 0,
.alias_via_thunk = 0,
.weak_undef_attr = "weak",
+ .weak_extern_underscore_alias = 1,
/* synth_inputs: the COFF __CTOR_LIST__/__DTOR_LIST__ + __chkstk
* synthesizer (link_synth_coff_ctor_dtor_list) genuinely needs Linker
* internals (LinkInput append, link_arch_desc_for); it cannot be
diff --git a/test/objdump/aarch64/cases/04-disasm-stripped-segment.expected b/test/objdump/aarch64/cases/04-disasm-stripped-segment.expected
@@ -144,7 +144,7 @@ Disassembly of segment LOAD:
40422c: b6 ff ff 97 bl 0x404104
404230: a0 43 1e b8 stur w0, [x29, #-28]
404234: a9 43 5e b8 ldur w9, [x29, #-28]
- 404238: 28 7d 40 93 sbfm x8, x9, #0, #31
+ 404238: 28 7d 40 93 sxtw x8, w9
40423c: a8 83 1d f8 stur x8, [x29, #-40]
404240: a0 83 5d f8 ldur x0, [x29, #-40]
404244: 6f ff ff 97 bl 0x404000