authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-11 19:41:18-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-11 19:41:18-05:00
log1a7c47d966b9f709b5aa842f0f9786b1d6970e3d
tree7ce327192e48b5414b6ff0310e3f22bf40305045
parent7c4c49ff07de31b1b74f3dc26648ad4000113256
parent975049e96e2245022a90368360fe7f3617e5f194
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10572 from Luukdegram/wasm-linker-stack

Stage2: wasm-linker - Place stack at the beginning of the linear memory

1 files changed, 26 insertions(+), 12 deletions(-)

src/link/Wasm.zig+26-12
......@@ -494,9 +494,21 @@ fn setupMemory(self: *Wasm) !void {
494494 log.debug("Setting up memory layout", .{});
495495 const page_size = 64 * 1024;
496496 const stack_size = self.base.options.stack_size_override orelse page_size * 1;
497 const stack_alignment = 16;
498 var memory_ptr: u64 = self.base.options.global_base orelse 1024;
499 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
497 const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention
498 // Always place the stack at the start by default
499 // unless the user specified the global-base flag
500 var place_stack_first = true;
501 var memory_ptr: u64 = if (self.base.options.global_base) |base| blk: {
502 place_stack_first = false;
503 break :blk base;
504 } else 0;
505
506 if (place_stack_first) {
507 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
508 memory_ptr += stack_size;
509 // We always put the stack pointer global at index 0
510 self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
511 }
500512
501513 var offset: u32 = @intCast(u32, memory_ptr);
502514 for (self.segments.items) |*segment, i| {
......@@ -510,8 +522,11 @@ fn setupMemory(self: *Wasm) !void {
510522 offset += segment.size;
511523 }
512524
513 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
514 memory_ptr += stack_size;
525 if (!place_stack_first) {
526 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
527 memory_ptr += stack_size;
528 self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
529 }
515530
516531 // Setup the max amount of pages
517532 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1
......@@ -554,9 +569,6 @@ fn setupMemory(self: *Wasm) !void {
554569 self.memories.limits.max = @intCast(u32, max_memory / page_size);
555570 log.debug("Maximum memory pages: {d}", .{self.memories.limits.max});
556571 }
557
558 // We always put the stack pointer global at index 0
559 self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
560572}
561573
562574fn resetState(self: *Wasm) void {
......@@ -1231,6 +1243,12 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
12311243 if (self.base.options.global_base) |global_base| {
12321244 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
12331245 try argv.append(arg);
1246 } else {
1247 // We prepend it by default, so when a stack overflow happens the runtime will trap correctly,
1248 // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496
1249 //
1250 // The user can overwrite this behavior by setting the global-base
1251 try argv.append("--stack-first");
12341252 }
12351253
12361254 var auto_export_symbols = true;
......@@ -1282,10 +1300,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
12821300 const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size});
12831301 try argv.append(arg);
12841302
1285 // Put stack before globals so that stack overflow results in segfault immediately
1286 // before corrupting globals. See https://github.com/ziglang/zig/issues/4496
1287 try argv.append("--stack-first");
1288
12891303 if (self.base.options.wasi_exec_model == .reactor) {
12901304 // Reactor execution model does not have _start so lld doesn't look for it.
12911305 try argv.append("--no-entry");