authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-07-01 10:36:28+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-07-07 13:05:31+01:00
logf6656470df9f2eab664c0137c187a1b82207e469
treec464a865f976436df49e128580b3407c1c2bbc11
parent2e5b6d814e5c71acf268c242c9519c3e3674bcba
signaturelock-open Commit is signed but in an unrecognized format.

Elf2: add support for custom stack size


1 files changed, 22 insertions(+), 2 deletions(-)

src/link/Elf2.zig+22-2
......@@ -2927,6 +2927,7 @@ fn initHeaders(
29272927 tls: u32,
29282928 dynamic: u32,
29292929 relro: u32,
2930 gnu_stack: u32,
29302931 }, const phnum: u32 = ph: {
29312932 switch (@"type") {
29322933 .NONE, .CORE, _ => unreachable,
......@@ -2967,12 +2968,16 @@ fn initHeaders(
29672968 defer phnum += 1;
29682969 break :phndx phnum;
29692970 },
2971 .gnu_stack = phndx: {
2972 defer phnum += 1;
2973 break :phndx phnum;
2974 },
29702975 }, phnum };
29712976 };
29722977
29732978 const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes
29742979 (shnum - 1) + // -1 because the null shdr does not have a `.section` node
2975 phnum;
2980 (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node
29762981
29772982 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
29782983 try elf.shdrs.ensureTotalCapacity(gpa, shnum);
......@@ -3085,6 +3090,8 @@ fn initHeaders(
30853090 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });
30863091 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;
30873092
3093 elf.phdrs.items[phndx.gnu_stack] = .none;
3094
30883095 break :ph_vaddr switch (elf.ehdrField(.type)) {
30893096 .NONE, .CORE, _ => unreachable,
30903097 .REL, .DYN => 0,
......@@ -3221,6 +3228,19 @@ fn initHeaders(
32213228 .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()),
32223229 };
32233230 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_relro);
3231
3232 const ph_gnu_stack = &phdr[phndx.gnu_stack];
3233 ph_gnu_stack.* = .{
3234 .type = .GNU_STACK,
3235 .offset = 0,
3236 .vaddr = 0,
3237 .paddr = 0,
3238 .filesz = 0,
3239 .memsz = @intCast(elf.options.stack_size orelse 0),
3240 .flags = .{ .R = true, .W = true },
3241 .@"align" = 1,
3242 };
3243 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_gnu_stack);
32243244 }
32253245
32263246 const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
......@@ -6896,7 +6916,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
68966916 switch (elf.targetLoad(&next_ph.type)) {
68976917 else => unreachable,
68986918 .NULL, .LOAD => {},
6899 .DYNAMIC, .INTERP, .PHDR, .TLS, std.elf.PT.GNU_RELRO => break,
6919 .DYNAMIC, .INTERP, .PHDR, .TLS, .GNU_RELRO, .GNU_STACK => break,
69006920 }
69016921 const next_vaddr = elf.targetLoad(&next_ph.vaddr);
69026922 if (vaddr + memsz <= next_vaddr) break;