| ... | ... | @@ -297,26 +297,47 @@ fn posixCallMainAndExit() noreturn { |
| 297 | 297 | std.os.linux.tls.initStaticTLS(); |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | | // TODO This is disabled because what should we do when linking libc and this code |
| 301 | | // does not execute? And also it's causing a test failure in stack traces in release modes. |
| 302 | | |
| 303 | | //// Linux ignores the stack size from the ELF file, and instead always does 8 MiB. A further |
| 304 | | //// problem is that it uses PROT_GROWSDOWN which prevents stores to addresses too far down |
| 305 | | //// the stack and requires "probing". So here we allocate our own stack. |
| 306 | | //const wanted_stack_size = gnu_stack_phdr.p_memsz; |
| 307 | | //assert(wanted_stack_size % std.mem.page_size == 0); |
| 308 | | //// Allocate an extra page as the guard page. |
| 309 | | //const total_size = wanted_stack_size + std.mem.page_size; |
| 310 | | //const new_stack = std.os.mmap( |
| 311 | | // null, |
| 312 | | // total_size, |
| 313 | | // std.os.PROT_READ | std.os.PROT_WRITE, |
| 314 | | // std.os.MAP_PRIVATE | std.os.MAP_ANONYMOUS, |
| 315 | | // -1, |
| 316 | | // 0, |
| 317 | | //) catch @panic("out of memory"); |
| 318 | | //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {}; |
| 319 | | //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp})); |
| 300 | // Linux ignores the stack size from the ELF file, and instead always gives 8 MiB. |
| 301 | // Here we look for the stack size in our program headers and tell the kernel, |
| 302 | // no, seriously, give me that stack space, I wasn't joking. |
| 303 | { |
| 304 | var i: usize = 0; |
| 305 | var at_phnum: usize = undefined; |
| 306 | var at_phdr: usize = undefined; |
| 307 | while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { |
| 308 | switch (auxv[i].a_type) { |
| 309 | std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, |
| 310 | std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, |
| 311 | else => continue, |
| 312 | } |
| 313 | } |
| 314 | const phdrs = (@intToPtr([*]std.elf.Phdr, at_phdr))[0..at_phnum]; |
| 315 | for (phdrs) |*phdr| { |
| 316 | switch (phdr.p_type) { |
| 317 | std.elf.PT_GNU_STACK => { |
| 318 | const wanted_stack_size = phdr.p_memsz; |
| 319 | assert(wanted_stack_size % std.mem.page_size == 0); |
| 320 | |
| 321 | std.os.setrlimit(.STACK, .{ |
| 322 | .cur = wanted_stack_size, |
| 323 | .max = wanted_stack_size, |
| 324 | }) catch { |
| 325 | // If this is a debug build, it will be useful to find out |
| 326 | // why this failed. If it is a release build, we allow the |
| 327 | // stack overflow to cause a segmentation fault. Memory safety |
| 328 | // is not compromised, however, depending on runtime state, |
| 329 | // the application may crash due to provided stack space not |
| 330 | // matching the known upper bound. |
| 331 | if (builtin.mode == .Debug) { |
| 332 | @panic("unable to increase stack size"); |
| 333 | } |
| 334 | }; |
| 335 | break; |
| 336 | }, |
| 337 | else => {}, |
| 338 | } |
| 339 | } |
| 340 | } |
| 320 | 341 | } |
| 321 | 342 | |
| 322 | 343 | std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp })); |