kit

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

commit 809a8e5e87c71ee3f3213e7e6f1f31eb972b70da
parent e87c69019725a0c08d8a1329614ac3e519758d9e
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri,  5 Jun 2026 21:00:54 -0700

Fix aarch64 COFF weak-null ADRP relocation

Diffstat:
Mdoc/plan/TODO.md | 9---------
Msrc/link/link_internal.h | 3+++
Msrc/link/link_layout.c | 40+++++++++++++++++++++++++++++++++-------
Msrc/link/link_reloc_layout.c | 5+++--
Msrc/obj/coff/link.c | 13+++++++++++++
5 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/doc/plan/TODO.md b/doc/plan/TODO.md @@ -5,15 +5,6 @@ fixed, remove it instead of checking it off or keeping a closed entry. Add new deferred fixes below as they are discovered. -## aarch64-windows: `118_decl_extra_attrs` fails to link (ADRP out of range) - -`kit cc -target aarch64-windows` on `test/toy/cases/118_decl_extra_attrs.toy` -aborts with `fatal: link: ADR_PREL_PG_HI21 out of range (need ±4GiB)` at both O0 -and O1. The same case links cleanly on x86_64-windows and aarch64-freebsd, so it -is aarch64-windows-specific. The case combines TLS-model attrs + ifunc/dllimport -+ section/merge attrs; the resulting aarch64-windows section/layout overflows an -ADRP page-relative relocation. Surfaced by `test-toy-windows-vm` (test/toy/vm.sh). - ## x86_64-windows: tail-call + sret miscompiles at O1 (access violation) `test/toy/cases/{36_musttail_sret,37_tail_sret}.toy` built `-target diff --git a/src/link/link_internal.h b/src/link/link_internal.h @@ -278,6 +278,9 @@ LinkRelocApply* link_append_reloc_slot(LinkImage* img); /* Emit or upsert a synthetic global boundary symbol (link_layout.c). */ void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, u64 vaddr); +void link_emit_section_boundary_sym(Linker* l, LinkImage* img, + const char* name, LinkSectionId section_id, + u64 value); /* Detect __start_<X> / __stop_<X> with <X> a valid C identifier. * Defined in link_resolve.c; used by link_reloc_layout.c. */ diff --git a/src/link/link_layout.c b/src/link/link_layout.c @@ -598,12 +598,16 @@ static Sym boundary_name(Linker* l, const char* name) { return obj_format_c_mangle(l->c, name); } -/* Upsert a global symbol with the given absolute vaddr. Satisfies any - * prior undef ref in place; fans out to per-input duplicate name slots. */ -void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, - u64 vaddr) { +/* Upsert a global boundary symbol. Satisfies any prior undef ref in place; fans + * out to per-input duplicate name slots. `section_id` is LINK_SEC_NONE for + * absolute boundaries, or the owning LinkSectionId for boundaries that must + * follow a format-specific section relayout. */ +static void link_emit_boundary_sym_ex(Linker* l, LinkImage* img, + const char* name, u64 vaddr, + LinkSectionId section_id, u64 value) { Sym sym = boundary_name(l, name); LinkSymId id = symhash_get(&img->globals, sym); + LinkSymId canonical_id = id; LinkSymbol rec; u8 kind = SK_OBJ; int fmt_kind; @@ -617,6 +621,8 @@ void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, rec.name = sym; rec.kind = kind; rec.defined = 1; + rec.section_id = section_id; + rec.value = value; rec.vaddr = vaddr; rec.bind = SB_GLOBAL; if (id != LINK_SYM_NONE) { @@ -625,15 +631,16 @@ void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, } else { LinkSymId fresh = link_append_symbol(img, &rec); symhash_insert(&img->globals, sym, fresh, &id); + canonical_id = fresh; } n = LinkSyms_count(&img->syms); for (i = 0; i < n; ++i) { LinkSymbol* s = LinkSyms_at(&img->syms, i); if (s->name != sym) continue; - if (s->id == id) continue; + if (s->id == canonical_id) continue; if (s->bind == SB_LOCAL) continue; - s->section_id = LINK_SEC_NONE; - s->value = 0; + s->section_id = section_id; + s->value = value; s->vaddr = vaddr; s->kind = kind; s->defined = 1; @@ -641,6 +648,25 @@ void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, } } +void link_emit_boundary_sym(Linker* l, LinkImage* img, const char* name, + u64 vaddr) { + link_emit_boundary_sym_ex(l, img, name, vaddr, LINK_SEC_NONE, 0); +} + +void link_emit_section_boundary_sym(Linker* l, LinkImage* img, + const char* name, LinkSectionId section_id, + u64 value) { + const LinkSection* sec; + u64 vaddr; + if (section_id == LINK_SEC_NONE || section_id > img->nsections) + compiler_panic(img->c, SRCLOC_NONE, + "link: boundary symbol '%.*s' has no containing section", + SLICE_ARG(slice_from_cstr(name))); + sec = &img->sections[section_id - 1]; + vaddr = sec->vaddr + (value - sec->obj_offset); + link_emit_boundary_sym_ex(l, img, name, vaddr, section_id, value); +} + /* link_define_boundary: public alias used by link_dyn.c. */ void link_define_boundary(Linker* l, LinkImage* img, const char* name, u64 vaddr) { diff --git a/src/link/link_reloc_layout.c b/src/link/link_reloc_layout.c @@ -726,8 +726,9 @@ void link_layout_iplt(Linker* l, LinkImage* img) { SF_ALLOC | SF_WRITE, SSEM_PREINIT_ARRAY, init_size, 8, &init_vaddr, NULL); - link_emit_boundary_sym(l, img, "__start_iplt_pairs", pairs_vaddr); - link_emit_boundary_sym(l, img, "__stop_iplt_pairs", pairs_vaddr + pairs_size); + link_emit_section_boundary_sym(l, img, "__start_iplt_pairs", pairs_sec_id, 0); + link_emit_section_boundary_sym(l, img, "__stop_iplt_pairs", pairs_sec_id, + pairs_size); if (use_rela_iplt) { /* One Elf64_Rela (24 bytes) per IFUNC: r_offset = igot slot, r_info = diff --git a/src/obj/coff/link.c b/src/obj/coff/link.c @@ -1352,6 +1352,19 @@ static void coff_apply_all_relocs(LinkImage* img, wr_u32_le(P_bytes, (u32)(v & 0xffffffffu)); continue; } + if (tgt->bind == SB_WEAK && tgt->kind == SK_ABS && tgt->vaddr == 0) { + /* AArch64 cannot generally ADRP from a PE image base down to absolute + * NULL. Materialize the weak-undef address as zero directly; the paired + * ADD low-12 relocation is already a no-op. */ + if (r->kind == R_AARCH64_ADR_PREL_PG_HI21 || + r->kind == R_AARCH64_ADR_PREL_PG_HI21_NC) { + u32 instr = rd_u32_le(P_bytes); + u32 rd = instr & 0x1fu; + wr_u32_le(P_bytes, 0xd2800000u | rd); /* movz Xrd, #0 */ + continue; + } + if (r->kind == R_AARCH64_ADD_ABS_LO12_NC) continue; + } link_reloc_apply(c, r->kind, P_bytes, S, r->addend, P); } }