kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 86578e086af87817f5e12c08978143bfc10f1946
parent e98db5738ea91cf5fe5953d9f5a9937a56377a59
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 17:22:42 -0700

link: treat DSO exports as defined so archives don't shadow shared libs

scan_presence_before classified a DSO export (cfree records it as an
OBJ_SEC_NONE global) as undefined via obj_sym_is_logical_undef, so when a
later static archive also defined the name, the archive member was pulled to
redefine a symbol the shared library already provides. Linking a -pie
executable against a real libc thus let libcfree_rt.a's freestanding
atoi/strtol shadow the libc's versions, breaking the dynamic 12_stdlib_convert
case in test-libc-musl-rv64 / test-libc-glibc-rv64.

Count a DSO's exported (non-SK_UNDEF) symbols as defined so a static-archive
member is not pulled to shadow them, matching standard ld behavior.

Diffstat:
Msrc/link/link_resolve.c | 12++++++++++++
1 file changed, 12 insertions(+), 0 deletions(-)

diff --git a/src/link/link_resolve.c b/src/link/link_resolve.c @@ -885,12 +885,24 @@ static void scan_presence_before(Linker* l, u32 max_order, SymHash* defined, for (ii = 0; ii < LinkInputs_count(&l->inputs); ++ii) { LinkInput* in = LinkInputs_at(&l->inputs, ii); ObjBuilder* ob = in->obj; + int is_dso = (in->kind == LINK_INPUT_DSO_BYTES); if (!ob || in->order > max_order) continue; it = obj_symiter_new(ob); while (obj_symiter_next(it, &e)) { const ObjSym* s = e.sym; if (s->name == 0) continue; if (s->bind == SB_LOCAL) continue; + if (is_dso) { + /* A DSO's exported symbols satisfy undefined references, so a later + * static-archive member must NOT be pulled to redefine them. cfree + * records DSO exports as OBJ_SEC_NONE globals (the importer's view), + * which obj_sym_is_logical_undef would otherwise misclassify as + * undefined — leaving e.g. a real libc's atoi looking unsatisfied and + * letting the freestanding rt's atoi shadow it. The DSO's own undefs + * (SK_UNDEF) are not exports and stay out of `defined`. */ + if (s->kind != SK_UNDEF) symhash_set(defined, s->name, 1u); + continue; + } if (obj_sym_is_logical_undef(s)) { /* Match the spurious-UNDEF prune in link_resolve (line 109) and * obj_sweep_dead at .o emit (obj.c:513): an unreferenced