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(...@@ -3574,6 +3574,7 @@ fn initHeaders(
3574 interp: u32,3574 interp: u32,
3575 rodata: u32,3575 rodata: u32,
3576 text: u32,3576 text: u32,
3577 /// HACKHACK: must be assigned after all other loadable segments so that the data segment always has the greatest vaddr on SPARC
3577 data: u32,3578 data: u32,
3578 /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write3579 /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write
3579 /// directly to the PLT, we place the PLT in its own segment in order to avoid making the3580 /// directly to the PLT, we place the PLT in its own segment in order to avoid making the
...@@ -3606,14 +3607,14 @@ fn initHeaders(...@@ -3606,14 +3607,14 @@ fn initHeaders(
3606 defer phnum += 1;3607 defer phnum += 1;
3607 break :phndx phnum;3608 break :phndx phnum;
3608 },3609 },
3609 .data = phndx: {
3610 defer phnum += 1;
3611 break :phndx phnum;
3612 },
3613 .plt = if (plt.got_plt == null) phndx: {3610 .plt = if (plt.got_plt == null) phndx: {
3614 defer phnum += 1;3611 defer phnum += 1;
3615 break :phndx phnum;3612 break :phndx phnum;
3616 } else undefined,3613 } else undefined,
3614 .data = phndx: {
3615 defer phnum += 1;
3616 break :phndx phnum;
3617 },
3617 .tls = if (comp.config.any_non_single_threaded) phndx: {3618 .tls = if (comp.config.any_non_single_threaded) phndx: {
3618 defer phnum += 1;3619 defer phnum += 1;
3619 break :phndx phnum;3620 break :phndx phnum;
...@@ -8357,6 +8358,19 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro...@@ -8357,6 +8358,19 @@ fn allocateSegmentLoadAddress(elf: *Elf, orig_phndx: u32) std.mem.Allocator.Erro
8357 break; // hooray, we fit here!8358 break; // hooray, we fit here!
8358 }8359 }
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
8360 // We don't fit here, so shift ourselves forward (i.e. swap with `next_phndx`). But8374 // We don't fit here, so shift ourselves forward (i.e. swap with `next_phndx`). But
8361 // first we need to adjust `vaddr` to come after it.8375 // first we need to adjust `vaddr` to come after it.
8362 const next_size = elf.targetLoad(&next_ph.memsz);8376 const next_size = elf.targetLoad(&next_ph.memsz);