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:
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