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(...@@ -2927,6 +2927,7 @@ fn initHeaders(
2927 tls: u32,2927 tls: u32,
2928 dynamic: u32,2928 dynamic: u32,
2929 relro: u32,2929 relro: u32,
2930 gnu_stack: u32,
2930 }, const phnum: u32 = ph: {2931 }, const phnum: u32 = ph: {
2931 switch (@"type") {2932 switch (@"type") {
2932 .NONE, .CORE, _ => unreachable,2933 .NONE, .CORE, _ => unreachable,
...@@ -2967,12 +2968,16 @@ fn initHeaders(...@@ -2967,12 +2968,16 @@ fn initHeaders(
2967 defer phnum += 1;2968 defer phnum += 1;
2968 break :phndx phnum;2969 break :phndx phnum;
2969 },2970 },
2971 .gnu_stack = phndx: {
2972 defer phnum += 1;
2973 break :phndx phnum;
2974 },
2970 }, phnum };2975 }, phnum };
2971 };2976 };
29722977
2973 const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes2978 const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes
2974 (shnum - 1) + // -1 because the null shdr does not have a `.section` node2979 (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
2977 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);2982 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
2978 try elf.shdrs.ensureTotalCapacity(gpa, shnum);2983 try elf.shdrs.ensureTotalCapacity(gpa, shnum);
...@@ -3085,6 +3090,8 @@ fn initHeaders(...@@ -3085,6 +3090,8 @@ fn initHeaders(
3085 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });3090 elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro });
3086 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;3091 elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro;
30873092
3093 elf.phdrs.items[phndx.gnu_stack] = .none;
3094
3088 break :ph_vaddr switch (elf.ehdrField(.type)) {3095 break :ph_vaddr switch (elf.ehdrField(.type)) {
3089 .NONE, .CORE, _ => unreachable,3096 .NONE, .CORE, _ => unreachable,
3090 .REL, .DYN => 0,3097 .REL, .DYN => 0,
...@@ -3221,6 +3228,19 @@ fn initHeaders(...@@ -3221,6 +3228,19 @@ fn initHeaders(
3221 .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()),3228 .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()),
3222 };3229 };
3223 if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_relro);3230 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);
3224 }3244 }
32253245
3226 const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));3246 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...@@ -6896,7 +6916,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo
6896 switch (elf.targetLoad(&next_ph.type)) {6916 switch (elf.targetLoad(&next_ph.type)) {
6897 else => unreachable,6917 else => unreachable,
6898 .NULL, .LOAD => {},6918 .NULL, .LOAD => {},
6899 .DYNAMIC, .INTERP, .PHDR, .TLS, std.elf.PT.GNU_RELRO => break,6919 .DYNAMIC, .INTERP, .PHDR, .TLS, .GNU_RELRO, .GNU_STACK => break,
6900 }6920 }
6901 const next_vaddr = elf.targetLoad(&next_ph.vaddr);6921 const next_vaddr = elf.targetLoad(&next_ph.vaddr);
6902 if (vaddr + memsz <= next_vaddr) break;6922 if (vaddr + memsz <= next_vaddr) break;