From dd9a64721030cf10065e74755f0c757cb470bcf3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jan 2025 17:03:03 -0800 Subject: [PATCH] wasm linker: fix bad export index math --- src/link/Wasm.zig | 29 +++++++++++++---------------- src/link/Wasm/Flush.zig | 14 ++++++-------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 5bc88a63d0..4b130fce00 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -207,7 +207,7 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty, entry_resolution: FunctionImport.Resolution = .unresolved, /// Empty when outputting an object. -function_exports: std.ArrayListUnmanaged(FunctionExport) = .empty, +function_exports: std.AutoArrayHashMapUnmanaged(String, FunctionIndex) = .empty, /// Tracks the value at the end of prelink. function_exports_len: u32 = 0, global_exports: std.ArrayListUnmanaged(GlobalExport) = .empty, @@ -353,8 +353,13 @@ pub const FunctionIndex = enum(u32) { } pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex { - const import = wasm.object_function_imports.getPtr(name) orelse return null; - return fromResolution(wasm, import.resolution); + if (wasm.object_function_imports.getPtr(name)) |import| { + return fromResolution(wasm, import.resolution); + } + if (wasm.function_exports.get(name)) |index| { + return index; + } + return null; } pub fn fromResolution(wasm: *const Wasm, resolution: FunctionImport.Resolution) ?FunctionIndex { @@ -363,11 +368,6 @@ pub const FunctionIndex = enum(u32) { } }; -pub const FunctionExport = extern struct { - name: String, - function_index: FunctionIndex, -}; - pub const GlobalExport = extern struct { name: String, global_index: GlobalIndex, @@ -386,7 +386,7 @@ pub const OutputFunctionIndex = enum(u32) { } pub fn fromFunctionIndex(wasm: *const Wasm, index: FunctionIndex) OutputFunctionIndex { - return @enumFromInt(wasm.function_imports.entries.len + @intFromEnum(index)); + return @enumFromInt(wasm.flush_buffer.function_imports.entries.len + @intFromEnum(index)); } pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex { @@ -410,8 +410,7 @@ pub const OutputFunctionIndex = enum(u32) { return switch (ip.indexToKey(ip_index)) { .@"extern" => |ext| { const name = wasm.getExistingString(ext.name.toSlice(ip)).?; - if (wasm.function_imports.getIndex(name)) |i| return @enumFromInt(i); - return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name).?); + return fromSymbolName(wasm, name); }, else => fromResolution(wasm, .fromIpIndex(wasm, ip_index)).?, }; @@ -3424,7 +3423,7 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v } } wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); - wasm.function_exports_len = @intCast(wasm.function_exports.items.len); + wasm.function_exports_len = @intCast(wasm.function_exports.entries.len); for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { if (import.flags.isIncluded(rdynamic)) { @@ -3498,10 +3497,8 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex) link.File.FlushError!void { const function = i.ptr(wasm); markObject(wasm, function.object_index); - if (!is_obj and function.flags.isExported(rdynamic)) try wasm.function_exports.append(gpa, .{ - .name = function.name.unwrap().?, - .function_index = @enumFromInt(gop.index), - }); + if (!is_obj and function.flags.isExported(rdynamic)) + try wasm.function_exports.put(gpa, function.name.unwrap().?, @enumFromInt(gop.index)); try wasm.markRelocations(function.relocations(wasm)); } diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 83c2df6053..5a7fbc091b 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -167,10 +167,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { for (wasm.nav_exports.keys()) |*nav_export| { if (ip.isFunctionType(ip.getNav(nav_export.nav_index).typeOf(ip))) { log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); - try wasm.function_exports.append(gpa, .{ - .name = nav_export.name, - .function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?, - }); + try wasm.function_exports.put(gpa, nav_export.name, Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?); _ = f.missing_exports.swapRemove(nav_export.name); _ = f.function_imports.swapRemove(nav_export.name); @@ -671,15 +668,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); var exports_len: usize = 0; - for (wasm.function_exports.items) |exp| { - const name = exp.name.slice(wasm); + for (wasm.function_exports.keys(), wasm.function_exports.values()) |exp_name, function_index| { + const name = exp_name.slice(wasm); try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len))); try binary_bytes.appendSlice(gpa, name); try binary_bytes.append(gpa, @intFromEnum(std.wasm.ExternalKind.function)); - const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, exp.function_index); + const func_index = Wasm.OutputFunctionIndex.fromFunctionIndex(wasm, function_index); try leb.writeUleb128(binary_writer, @intFromEnum(func_index)); } - exports_len += wasm.function_exports.items.len; + exports_len += wasm.function_exports.entries.len; // No table exports. @@ -709,6 +706,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } } + // start section if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); replaceVecSectionHeader(binary_bytes, header_offset, .start, @intFromEnum(func_index));