From 7b5d1a5d0ef24f1dceec0b206b952517a8027c68 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 13 Aug 2026 22:42:01 +0100 Subject: [PATCH] HACKHACK: Elf2: keep the data segment at the end so sparc's dumb got relocs are happy don't merge this, it's inefficient and bad --- src/link/Elf2.zig | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 54d38a2addf8ac922cad02d1e58e1ed127abb93f..b14144f178fe5b924e703ac67aa7973b47d06c87 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -3574,6 +3574,7 @@ fn initHeaders( interp: u32, rodata: u32, text: u32, + /// HACKHACK: must be assigned after all other loadable segments so that the data segment always has the greatest vaddr on SPARC data: u32, /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write /// directly to the PLT, we place the PLT in its own segment in order to avoid making the @@ -3606,14 +3607,14 @@ fn initHeaders( defer phnum += 1; break :phndx phnum; }, - .data = phndx: { - defer phnum += 1; - break :phndx phnum; - }, .plt = if (plt.got_plt == null) phndx: { defer phnum += 1; break :phndx phnum; } else undefined, + .data = phndx: { + defer phnum += 1; + break :phndx phnum; + }, .tls = if (comp.config.any_non_single_threaded) phndx: { defer phnum += 1; break :phndx phnum; @@ -8357,6 +8358,19 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro break; // hooray, we fit here! } + if (elf.phdrs.items[next_phndx] == elf.ni.data.toOptional()) { + // HACKHACK: make sparc happy by keeping the data segment at the end + // so, use the current candidate `vaddr` and just move the data segment's vaddr out of the way + const next_ni = elf.phdrs.items[next_phndx].unwrap().?; + const next_align = page_align.max(next_ni.alignment(&elf.mf)); + const next_offset = elf.targetLoad(&next_ph.offset); + const next_new_vaddr = next_align.forward(vaddr + target_size) + next_offset % next_align.toByteUnits(); + elf.targetStore(&next_ph.vaddr, @intCast(next_new_vaddr)); + elf.targetStore(&next_ph.paddr, @intCast(next_new_vaddr)); + try next_ni.childrenMoved(elf.base.comp.gpa, &elf.mf); + break; + } + // We don't fit here, so shift ourselves forward (i.e. swap with `next_phndx`). But // first we need to adjust `vaddr` to come after it. const next_size = elf.targetLoad(&next_ph.memsz); -- 2.54.0