Commit be08d2bdbd

Luuk de Gram <luuk@degram.dev>
2022-04-17 19:41:05
wasm: Fix unreachable paths
When the last instruction is a debug instruction, the type of it is void. Similarly for 'noreturn' emit an 'unreachable' instruction to tell the wasm-validator the path cannot be reached. Also respect the '--strip' flag in the self-hosted wasm linker and not emit a 'name' section when the flag is set to `true`.
1 parent 2193f7c
Changed files (3)
lib
src
arch
link
lib/std/debug.zig
@@ -113,11 +113,14 @@ pub fn detectTTYConfig() TTY.Config {
 /// TODO multithreaded awareness
 pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
     nosuspend {
-        const stderr = io.getStdErr().writer();
         if (comptime builtin.target.isWasm()) {
-            stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
+            if (native_os == .wasi) {
+                const stderr = io.getStdErr().writer();
+                stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
+            }
             return;
         }
+        const stderr = io.getStdErr().writer();
         if (builtin.strip_debug_info) {
             stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
             return;
@@ -138,6 +141,13 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
 /// TODO multithreaded awareness
 pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
     nosuspend {
+        if (comptime builtin.target.isWasm()) {
+            if (native_os == .wasi) {
+                const stderr = io.getStdErr().writer();
+                stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
+            }
+            return;
+        }
         const stderr = io.getStdErr().writer();
         if (builtin.strip_debug_info) {
             stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
@@ -208,6 +218,13 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
 /// TODO multithreaded awareness
 pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
     nosuspend {
+        if (comptime builtin.target.isWasm()) {
+            if (native_os == .wasi) {
+                const stderr = io.getStdErr().writer();
+                stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
+            }
+            return;
+        }
         const stderr = io.getStdErr().writer();
         if (builtin.strip_debug_info) {
             stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return;
@@ -1138,6 +1155,8 @@ pub const DebugInfo = struct {
             return self.lookupModuleWin32(address);
         } else if (native_os == .haiku) {
             return self.lookupModuleHaiku(address);
+        } else if (comptime builtin.target.isWasm()) {
+            return self.lookupModuleWasm(address);
         } else {
             return self.lookupModuleDl(address);
         }
@@ -1353,6 +1372,12 @@ pub const DebugInfo = struct {
         _ = address;
         @panic("TODO implement lookup module for Haiku");
     }
+
+    fn lookupModuleWasm(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
+        _ = self;
+        _ = address;
+        @panic("TODO implement lookup module for Wasm");
+    }
 };
 
 pub const ModuleDebugInfo = switch (native_os) {
@@ -1632,6 +1657,13 @@ pub const ModuleDebugInfo = switch (native_os) {
             return getSymbolFromDwarf(relocated_address, &self.dwarf);
         }
     },
+    .wasi => struct {
+        pub fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo {
+            _ = self;
+            _ = address;
+            return SymbolInfo{};
+        }
+    },
     else => DW.DwarfInfo,
 };
 
src/arch/wasm/CodeGen.zig
@@ -871,7 +871,8 @@ fn genFunc(self: *Self) InnerError!void {
     // we emit an unreachable instruction to tell the stack validator that part will never be reached.
     if (func_type.returns.len != 0 and self.air.instructions.len > 0) {
         const inst = @intCast(u32, self.air.instructions.len - 1);
-        if (self.air.typeOfIndex(inst).isNoReturn()) {
+        const last_inst_ty = self.air.typeOfIndex(inst);
+        if (!last_inst_ty.hasRuntimeBitsIgnoreComptime() or last_inst_ty.isNoReturn()) {
             try self.addTag(.@"unreachable");
         }
     }
src/link/Wasm.zig
@@ -1897,7 +1897,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
         if (data_section_index) |data_index| {
             try self.emitDataRelocations(file, arena, data_index, symbol_table);
         }
-    } else {
+    } else if (!self.base.options.strip) {
         try self.emitNameSection(file, arena);
     }
 }