| ... | ... | @@ -495,9 +495,21 @@ fn setupMemory(self: *Wasm) !void { |
| 495 | 495 | log.debug("Setting up memory layout", .{}); |
| 496 | 496 | const page_size = 64 * 1024; |
| 497 | 497 | const stack_size = self.base.options.stack_size_override orelse page_size * 1; |
| 498 | | const stack_alignment = 16; |
| 499 | | var memory_ptr: u64 = self.base.options.global_base orelse 1024; |
| 500 | | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment); |
| 498 | const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention |
| 499 | // Always place the stack at the start by default |
| 500 | // unless the user specified the global-base flag |
| 501 | var place_stack_first = true; |
| 502 | var memory_ptr: u64 = if (self.base.options.global_base) |base| blk: { |
| 503 | place_stack_first = false; |
| 504 | break :blk base; |
| 505 | } else 0; |
| 506 | |
| 507 | if (place_stack_first) { |
| 508 | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment); |
| 509 | memory_ptr += stack_size; |
| 510 | // We always put the stack pointer global at index 0 |
| 511 | self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr)); |
| 512 | } |
| 501 | 513 | |
| 502 | 514 | var offset: u32 = @intCast(u32, memory_ptr); |
| 503 | 515 | for (self.segments.items) |*segment, i| { |
| ... | ... | @@ -511,8 +523,11 @@ fn setupMemory(self: *Wasm) !void { |
| 511 | 523 | offset += segment.size; |
| 512 | 524 | } |
| 513 | 525 | |
| 514 | | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment); |
| 515 | | memory_ptr += stack_size; |
| 526 | if (!place_stack_first) { |
| 527 | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment); |
| 528 | memory_ptr += stack_size; |
| 529 | self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr)); |
| 530 | } |
| 516 | 531 | |
| 517 | 532 | // Setup the max amount of pages |
| 518 | 533 | // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1 |
| ... | ... | @@ -555,9 +570,6 @@ fn setupMemory(self: *Wasm) !void { |
| 555 | 570 | self.memories.limits.max = @intCast(u32, max_memory / page_size); |
| 556 | 571 | log.debug("Maximum memory pages: {d}", .{self.memories.limits.max}); |
| 557 | 572 | } |
| 558 | | |
| 559 | | // We always put the stack pointer global at index 0 |
| 560 | | self.globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr)); |
| 561 | 573 | } |
| 562 | 574 | |
| 563 | 575 | fn resetState(self: *Wasm) void { |
| ... | ... | @@ -1105,6 +1117,12 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1105 | 1117 | if (self.base.options.global_base) |global_base| { |
| 1106 | 1118 | const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base}); |
| 1107 | 1119 | try argv.append(arg); |
| 1120 | } else { |
| 1121 | // We prepend it by default, so when a stack overflow happens the runtime will trap correctly, |
| 1122 | // rather than silently overwrite all global declarations. See https://github.com/ziglang/zig/issues/4496 |
| 1123 | // |
| 1124 | // The user can overwrite this behavior by setting the global-base |
| 1125 | try argv.append("--stack-first"); |
| 1108 | 1126 | } |
| 1109 | 1127 | |
| 1110 | 1128 | // Users are allowed to specify which symbols they want to export to the wasm host. |
| ... | ... | @@ -1125,10 +1143,6 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { |
| 1125 | 1143 | const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); |
| 1126 | 1144 | try argv.append(arg); |
| 1127 | 1145 | |
| 1128 | | // Put stack before globals so that stack overflow results in segfault immediately |
| 1129 | | // before corrupting globals. See https://github.com/ziglang/zig/issues/4496 |
| 1130 | | try argv.append("--stack-first"); |
| 1131 | | |
| 1132 | 1146 | if (self.base.options.wasi_exec_model == .reactor) { |
| 1133 | 1147 | // Reactor execution model does not have _start so lld doesn't look for it. |
| 1134 | 1148 | try argv.append("--no-entry"); |