authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-13 22:42:01+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-25 23:01:18+01:00
log7b5d1a5d0ef24f1dceec0b206b952517a8027c68
tree5f87efdd00fe5c793bf9a6adfa04e388c5fb9223
parent1a87c894a729b290cc2e9553fa9d16e1b0eb5453
signaturelock-open Commit is signed but in an unrecognized format.

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

1 files changed, 18 insertions(+), 4 deletions(-)

src/link/Elf2.zig+18-4
......@@ -3574,6 +3574,7 @@ fn initHeaders(
35743574 interp: u32,
35753575 rodata: u32,
35763576 text: u32,
3577 /// HACKHACK: must be assigned after all other loadable segments so that the data segment always has the greatest vaddr on SPARC
35773578 data: u32,
35783579 /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write
35793580 /// directly to the PLT, we place the PLT in its own segment in order to avoid making the
......@@ -3606,14 +3607,14 @@ fn initHeaders(
36063607 defer phnum += 1;
36073608 break :phndx phnum;
36083609 },
3609 .data = phndx: {
3610 defer phnum += 1;
3611 break :phndx phnum;
3612 },
36133610 .plt = if (plt.got_plt == null) phndx: {
36143611 defer phnum += 1;
36153612 break :phndx phnum;
36163613 } else undefined,
3614 .data = phndx: {
3615 defer phnum += 1;
3616 break :phndx phnum;
3617 },
36173618 .tls = if (comp.config.any_non_single_threaded) phndx: {
36183619 defer phnum += 1;
36193620 break :phndx phnum;
......@@ -8357,6 +8358,19 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro
83578358 break; // hooray, we fit here!
83588359 }
83598360
8361 if (elf.phdrs.items[next_phndx] == elf.ni.data.toOptional()) {
8362 // HACKHACK: make sparc happy by keeping the data segment at the end
8363 // so, use the current candidate `vaddr` and just move the data segment's vaddr out of the way
8364 const next_ni = elf.phdrs.items[next_phndx].unwrap().?;
8365 const next_align = page_align.max(next_ni.alignment(&elf.mf));
8366 const next_offset = elf.targetLoad(&next_ph.offset);
8367 const next_new_vaddr = next_align.forward(vaddr + target_size) + next_offset % next_align.toByteUnits();
8368 elf.targetStore(&next_ph.vaddr, @intCast(next_new_vaddr));
8369 elf.targetStore(&next_ph.paddr, @intCast(next_new_vaddr));
8370 try next_ni.childrenMoved(elf.base.comp.gpa, &elf.mf);
8371 break;
8372 }
8373
83608374 // We don't fit here, so shift ourselves forward (i.e. swap with `next_phndx`). But
83618375 // first we need to adjust `vaddr` to come after it.
83628376 const next_size = elf.targetLoad(&next_ph.memsz);