| ... | ... | @@ -2927,6 +2927,7 @@ fn initHeaders( |
| 2927 | 2927 | tls: u32, |
| 2928 | 2928 | dynamic: u32, |
| 2929 | 2929 | relro: u32, |
| 2930 | gnu_stack: u32, |
| 2930 | 2931 | }, const phnum: u32 = ph: { |
| 2931 | 2932 | switch (@"type") { |
| 2932 | 2933 | .NONE, .CORE, _ => unreachable, |
| ... | ... | @@ -2967,12 +2968,16 @@ fn initHeaders( |
| 2967 | 2968 | defer phnum += 1; |
| 2968 | 2969 | break :phndx phnum; |
| 2969 | 2970 | }, |
| 2971 | .gnu_stack = phndx: { |
| 2972 | defer phnum += 1; |
| 2973 | break :phndx phnum; |
| 2974 | }, |
| 2970 | 2975 | }, phnum }; |
| 2971 | 2976 | }; |
| 2972 | 2977 | |
| 2973 | 2978 | const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes |
| 2974 | 2979 | (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 |
| 2976 | 2981 | |
| 2977 | 2982 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 2978 | 2983 | try elf.shdrs.ensureTotalCapacity(gpa, shnum); |
| ... | ... | @@ -3085,6 +3090,8 @@ fn initHeaders( |
| 3085 | 3090 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro }); |
| 3086 | 3091 | elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro; |
| 3087 | 3092 | |
| 3093 | elf.phdrs.items[phndx.gnu_stack] = .none; |
| 3094 | |
| 3088 | 3095 | break :ph_vaddr switch (elf.ehdrField(.type)) { |
| 3089 | 3096 | .NONE, .CORE, _ => unreachable, |
| 3090 | 3097 | .REL, .DYN => 0, |
| ... | ... | @@ -3221,6 +3228,19 @@ fn initHeaders( |
| 3221 | 3228 | .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()), |
| 3222 | 3229 | }; |
| 3223 | 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 | } |
| 3225 | 3245 | |
| 3226 | 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 | 6916 | switch (elf.targetLoad(&next_ph.type)) { |
| 6897 | 6917 | else => unreachable, |
| 6898 | 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 | 6921 | const next_vaddr = elf.targetLoad(&next_ph.vaddr); |
| 6902 | 6922 | if (vaddr + memsz <= next_vaddr) break; |