authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-07 21:34:53-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-07 21:34:53-07:00
log6ec24a6502833e5bce582294ef6691173095ead7
tree7baf8afc16e0508f6abb70f17900d2c2515f0a95
parentf69cf930648999cedd0716c6804f46b0c1fbf504

std: start code on linux when -lc also expands stack size

See #8708

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

lib/std/start.zig+38-27
...@@ -302,8 +302,8 @@ fn posixCallMainAndExit() noreturn {...@@ -302,8 +302,8 @@ fn posixCallMainAndExit() noreturn {
302 // no, seriously, give me that stack space, I wasn't joking.302 // no, seriously, give me that stack space, I wasn't joking.
303 {303 {
304 var i: usize = 0;304 var i: usize = 0;
305 var at_phnum: usize = undefined;
306 var at_phdr: usize = undefined;305 var at_phdr: usize = undefined;
306 var at_phnum: usize = undefined;
307 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {307 while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
308 switch (auxv[i].a_type) {308 switch (auxv[i].a_type) {
309 std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,309 std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
...@@ -311,38 +311,42 @@ fn posixCallMainAndExit() noreturn {...@@ -311,38 +311,42 @@ fn posixCallMainAndExit() noreturn {
311 else => continue,311 else => continue,
312 }312 }
313 }313 }
314 const phdrs = (@intToPtr([*]std.elf.Phdr, at_phdr))[0..at_phnum];314 expandStackSize(at_phdr, 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 }315 }
341 }316 }
342317
343 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));318 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
344}319}
345320
321fn expandStackSize(at_phdr: usize, at_phnum: usize) void {
322 const phdrs = (@intToPtr([*]std.elf.Phdr, at_phdr))[0..at_phnum];
323 for (phdrs) |*phdr| {
324 switch (phdr.p_type) {
325 std.elf.PT_GNU_STACK => {
326 const wanted_stack_size = phdr.p_memsz;
327 assert(wanted_stack_size % std.mem.page_size == 0);
328
329 std.os.setrlimit(.STACK, .{
330 .cur = wanted_stack_size,
331 .max = wanted_stack_size,
332 }) catch {
333 // If this is a debug build, it will be useful to find out
334 // why this failed. If it is a release build, we allow the
335 // stack overflow to cause a segmentation fault. Memory safety
336 // is not compromised, however, depending on runtime state,
337 // the application may crash due to provided stack space not
338 // matching the known upper bound.
339 if (builtin.mode == .Debug) {
340 @panic("unable to increase stack size");
341 }
342 };
343 break;
344 },
345 else => {},
346 }
347 }
348}
349
346fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {350fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
347 std.os.argv = argv[0..argc];351 std.os.argv = argv[0..argc];
348 std.os.environ = envp;352 std.os.environ = envp;
...@@ -356,6 +360,13 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)...@@ -356,6 +360,13 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
356 var env_count: usize = 0;360 var env_count: usize = 0;
357 while (c_envp[env_count] != null) : (env_count += 1) {}361 while (c_envp[env_count] != null) : (env_count += 1) {}
358 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];362 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
363
364 if (builtin.os.tag == .linux) {
365 const at_phdr = std.c.getauxval(std.elf.AT_PHDR);
366 const at_phnum = std.c.getauxval(std.elf.AT_PHNUM);
367 expandStackSize(at_phdr, at_phnum);
368 }
369
359 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });370 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
360}371}
361372