kit

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

commit 0cf3dff4e27ef007e400dc08a2216d98d85ba21a
parent adf6261f0dc335fc1fb5d38afb5d9b5a4cf066ec
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 16 Jun 2026 15:26:03 -0700

link: skip relocation into a NOLOAD/NOBITS output section (Bug 3)

A NOLOAD output section forces every unit to SSEM_NOBITS with file_size 0, so
its segment's segment_bytes stays NULL. But a relocated PROGBITS input routed
into a NOLOAD output is still 'kept' (link_section_kept ignores NOLOAD), so its
reloc is collected with a real segment_id and apply_all_relocs reached the
P_bytes = segment_bytes[seg->id-1] (NULL) + offset path, writing through a NULL
pointer (UBSan: store to null pointer; e.g. a __attribute__((section(".shadow")))
pointer initializer in a (NOLOAD) .shadow).

Guard apply_all_relocs: after fetching the segment, if its segment_bytes is NULL
the section has no on-disk bytes -> skip the reloc (the value cannot be
observed at runtime), mirroring the file-only and NOBITS handling.

Test (test/buildcmds): fx2-noload-reloc links a C pointer initializer
(R_ABS64) into a (NOLOAD) section via a script and asserts the link succeeds.

Diffstat:
Msrc/obj/elf/link.c | 7+++++++
1 file changed, 7 insertions(+), 0 deletions(-)

diff --git a/src/obj/elf/link.c b/src/obj/elf/link.c @@ -629,6 +629,13 @@ static void apply_all_relocs(LinkImage* img, u64 img_base) { continue; } seg = &img->segments[sec->segment_id - 1]; + /* NOLOAD / NOBITS output section: the segment carries no on-disk bytes + * (segment_bytes left NULL), so there is no patch site to write. A kept + * PROGBITS input routed into a NOLOAD output (link_section_kept ignores + * NOLOAD) still collects its relocs with a real segment_id, but the value + * can never be observed at runtime — skip the apply rather than dereference + * a NULL segment buffer (mirrors the file-only branch above). */ + if (img->segment_bytes[seg->id - 1] == NULL) continue; if (reloc_is_tlsle(r->kind, tls_vi) || reloc_is_x64_tlsle(r->kind, tls_vi)) /* Both the direct local-exec relocs and the internal R_TPOFF64 used to * fill a TLS-IE GOT slot resolve to a tp-relative offset within THIS