authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-18 15:10:50-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:35-08:00
log85b53730fe248cf02468a213903ddac4bffe8234
tree22f04c8edeed5562a6dce6383fdf55c846f69317
parent2d899e9a9f0864385939955902e0ba5f322176fc

add safety for calling functions that get virtual addrs


3 files changed, 20 insertions(+), 8 deletions(-)

src/arch/wasm/Emit.zig+6-5
...@@ -108,7 +108,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {...@@ -108,7 +108,7 @@ pub fn lowerToCode(emit: *Emit) Error!void {
108 inst += 1;108 inst += 1;
109 continue :loop tags[inst];109 continue :loop tags[inst];
110 } else {110 } else {
111 const addr = try wasm.errorNameTableAddr();111 const addr: u32 = wasm.errorNameTableAddr();
112 leb.writeIleb128(code.fixedWriter(), addr) catch unreachable;112 leb.writeIleb128(code.fixedWriter(), addr) catch unreachable;
113113
114 inst += 1;114 inst += 1;
...@@ -931,7 +931,7 @@ fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef...@@ -931,7 +931,7 @@ fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef
931 try code.ensureUnusedCapacity(gpa, 11);931 try code.ensureUnusedCapacity(gpa, 11);
932 code.appendAssumeCapacity(@intFromEnum(opcode));932 code.appendAssumeCapacity(@intFromEnum(opcode));
933933
934 const addr = try wasm.uavAddr(data.uav_exe);934 const addr = wasm.uavAddr(data.uav_exe);
935 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;935 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;
936}936}
937937
...@@ -957,8 +957,9 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff...@@ -957,8 +957,9 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff
957 });957 });
958 code.appendNTimesAssumeCapacity(0, 5);958 code.appendNTimesAssumeCapacity(0, 5);
959 } else {959 } else {
960 const addr = try wasm.navAddr(data.nav_index);960 const function_imports_len: u32 = @intCast(wasm.function_imports.entries.len);
961 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;961 const func_index = Wasm.FunctionIndex.fromIpNav(wasm, data.nav_index).?;
962 leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable;
962 }963 }
963 } else {964 } else {
964 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;965 const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const;
...@@ -972,7 +973,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff...@@ -972,7 +973,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff
972 });973 });
973 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);974 code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10);
974 } else {975 } else {
975 const addr = try wasm.navAddr(data.nav_index);976 const addr = wasm.navAddr(data.nav_index);
976 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;977 leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable;
977 }978 }
978 }979 }
src/link/Wasm.zig+9-3
...@@ -3331,21 +3331,27 @@ pub fn refUavExe(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Ua...@@ -3331,21 +3331,27 @@ pub fn refUavExe(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Ua
3331 return uav_index;3331 return uav_index;
3332}3332}
33333333
3334pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) Allocator.Error!u32 {3334/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted.
3335pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
3336 assert(wasm.flush_buffer.memory_layout_finished);
3335 const comp = wasm.base.comp;3337 const comp = wasm.base.comp;
3336 assert(comp.config.output_mode != .Obj);3338 assert(comp.config.output_mode != .Obj);
3337 const ds_id: DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_index });3339 const ds_id: DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_index });
3338 return wasm.data_segments.get(ds_id).?;3340 return wasm.data_segments.get(ds_id).?;
3339}3341}
33403342
3341pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!u32 {3343/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted.
3344pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 {
3345 assert(wasm.flush_buffer.memory_layout_finished);
3342 const comp = wasm.base.comp;3346 const comp = wasm.base.comp;
3343 assert(comp.config.output_mode != .Obj);3347 assert(comp.config.output_mode != .Obj);
3344 const ds_id: DataSegment.Id = .pack(wasm, .{ .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?) });3348 const ds_id: DataSegment.Id = .pack(wasm, .{ .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?) });
3345 return wasm.data_segments.get(ds_id).?;3349 return wasm.data_segments.get(ds_id).?;
3346}3350}
33473351
3348pub fn errorNameTableAddr(wasm: *Wasm) Allocator.Error!u32 {3352/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted.
3353pub fn errorNameTableAddr(wasm: *Wasm) u32 {
3354 assert(wasm.flush_buffer.memory_layout_finished);
3349 const comp = wasm.base.comp;3355 const comp = wasm.base.comp;
3350 assert(comp.config.output_mode != .Obj);3356 assert(comp.config.output_mode != .Obj);
3351 return wasm.data_segments.get(.__zig_error_name_table).?;3357 return wasm.data_segments.get(.__zig_error_name_table).?;
src/link/Wasm/Flush.zig+5
...@@ -28,10 +28,14 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty,...@@ -28,10 +28,14 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty,
2828
29indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, u32) = .empty,29indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, u32) = .empty,
3030
31/// For debug purposes only.
32memory_layout_finished: bool = false,
33
31pub fn clear(f: *Flush) void {34pub fn clear(f: *Flush) void {
32 f.binary_bytes.clearRetainingCapacity();35 f.binary_bytes.clearRetainingCapacity();
33 f.data_segment_groups.clearRetainingCapacity();36 f.data_segment_groups.clearRetainingCapacity();
34 f.indirect_function_table.clearRetainingCapacity();37 f.indirect_function_table.clearRetainingCapacity();
38 f.memory_layout_finished = false;
35}39}
3640
37pub fn deinit(f: *Flush, gpa: Allocator) void {41pub fn deinit(f: *Flush, gpa: Allocator) void {
...@@ -348,6 +352,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -348,6 +352,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
348 if (shared_memory) wasm.memories.limits.flags.is_shared = true;352 if (shared_memory) wasm.memories.limits.flags.is_shared = true;
349 log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max});353 log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max});
350 }354 }
355 f.memory_layout_finished = true;
351356
352 var section_index: u32 = 0;357 var section_index: u32 = 0;
353 // Index of the code section. Used to tell relocation table where the section lives.358 // Index of the code section. Used to tell relocation table where the section lives.