authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-26 09:14:45+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-08-29 12:24:14+01:00
log3d4aabdf795edcb1e131ed3a2e3c2910d8343c85
tree88a9e0e4b77c7412d7ccde79306229fbcd403bbd
parent56c1b0871c396155ca865b4f3531f6a7f17b35a0
signaturelock-open Commit is signed but in an unrecognized format.

Elf2: align the initial PLT size

I had kind of assumed that every target's PLT was no more aligned than the size of an entire PLT entry, but apparently SPARC was determined to prove me wrong on that front.

1 files changed, 38 insertions(+), 27 deletions(-)

src/link/Elf2.zig+38-27
...@@ -4099,33 +4099,44 @@ fn initHeaders(...@@ -4099,33 +4099,44 @@ fn initHeaders(
4099 .addralign = addr_align,4099 .addralign = addr_align,
4100 .entsize = @intCast(addr_align.toByteUnits()),4100 .entsize = @intCast(addr_align.toByteUnits()),
4101 });4101 });
4102 if (plt.got_plt) |got_plt| {4102 {
4103 const got_plt_segment_ni = if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data;4103 const init_plt_size = plt.entry_size * plt.header_entries;
4104 elf.shndx.got_plt = try elf.addSection(got_plt_segment_ni, .{4104 if (plt.got_plt) |got_plt| {
4105 .name = ".got.plt",4105 const got_plt_segment_ni = if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data;
4106 .type = .PROGBITS,4106 elf.shndx.got_plt = try elf.addSection(got_plt_segment_ni, .{
4107 .flags = .{ .WRITE = true, .ALLOC = true },4107 .name = ".got.plt",
4108 .size = got_plt.header_entries * elf.targetPtrSize(),4108 .type = .PROGBITS,
4109 .addralign = addr_align,4109 .flags = .{ .WRITE = true, .ALLOC = true },
4110 .entsize = @intCast(addr_align.toByteUnits()),4110 .size = got_plt.header_entries * elf.targetPtrSize(),
4111 });4111 .addralign = addr_align,
4112 elf.shndx.plt = try elf.addSection(elf.ni.text, .{4112 .entsize = @intCast(addr_align.toByteUnits()),
4113 .name = ".plt",4113 });
4114 .type = .PROGBITS,4114 elf.shndx.plt = try elf.addSection(elf.ni.text, .{
4115 .flags = .{ .ALLOC = true, .EXECINSTR = true },4115 .name = ".plt",
4116 .size = plt.entry_size * plt.header_entries,4116 .type = .PROGBITS,
4117 .addralign = plt.@"align",4117 .flags = .{ .ALLOC = true, .EXECINSTR = true },
4118 .node_align = node_block_align,4118 .size = plt.@"align".forward(init_plt_size),
4119 });4119 .addralign = plt.@"align",
4120 } else {4120 .node_align = node_block_align,
4121 elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{4121 });
4122 .name = ".plt",4122 } else {
4123 .type = .PROGBITS,4123 elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt].unwrap().?, .{
4124 .flags = .{ .ALLOC = true, .WRITE = true, .EXECINSTR = true },4124 .name = ".plt",
4125 .size = plt.entry_size * plt.header_entries,4125 .type = .PROGBITS,
4126 .addralign = plt.@"align",4126 .flags = .{ .ALLOC = true, .WRITE = true, .EXECINSTR = true },
4127 .node_align = node_block_align,4127 .size = plt.@"align".forward(init_plt_size),
4128 });4128 .addralign = plt.@"align",
4129 .node_align = node_block_align,
4130 });
4131 }
4132 // And the award for most annoying PLT requirement goes to SPARC, which decided that the
4133 // whole table should have a greater alignment than the size of the individual entries,
4134 // hence this bullshit:
4135 if (plt.@"align".forward(init_plt_size) != init_plt_size) {
4136 switch (elf.shdrPtr(elf.shndx.plt)) {
4137 inline else => |shdr| elf.targetStore(&shdr.size, init_plt_size),
4138 }
4139 }
4129 }4140 }
4130 if (plt.plt_sec != null) elf.shndx.plt_sec = try elf.addSection(elf.ni.text, .{4141 if (plt.plt_sec != null) elf.shndx.plt_sec = try elf.addSection(elf.ni.text, .{
4131 .name = ".plt.sec",4142 .name = ".plt.sec",