diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 626f176652..37e25e4360 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -378,7 +378,7 @@ fn parseObjectFile(self: *Wasm, path: []const u8) !bool { const file = try fs.cwd().openFile(path, .{}); errdefer file.close(); - var object = Object.create(self.base.allocator, file, path) catch |err| switch (err) { + var object = Object.create(self.base.allocator, file, path, null) catch |err| switch (err) { error.InvalidMagicByte, error.NotObjectFile => return false, else => |e| return e, }; @@ -595,8 +595,8 @@ fn resolveSymbolsInArchives(self: *Wasm) !void { // Parse object and and resolve symbols again before we check remaining // undefined symbols. const object_file_index = @intCast(u16, self.objects.items.len); - const object = try self.objects.addOne(self.base.allocator); - object.* = try archive.parseObject(self.base.allocator, offset.items[0]); + var object = try archive.parseObject(self.base.allocator, offset.items[0]); + try self.objects.append(self.base.allocator, object); try self.resolveSymbolsInObject(object_file_index); // continue loop for any remaining undefined symbols that still exist @@ -860,7 +860,8 @@ fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType { if (is_undefined) { return obj.findImport(.global, symbol.index).kind.global; } - return obj.globals[symbol.index].global_type; + const import_global_count = obj.importedCountByKind(.global); + return obj.globals[symbol.index - import_global_count].global_type; } if (is_undefined) { return self.imports.get(loc).?.kind.global; @@ -880,7 +881,9 @@ fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type { const ty_index = obj.findImport(.function, symbol.index).kind.function; return obj.func_types[ty_index]; } - return obj.func_types[obj.functions[symbol.index].type_index]; + const import_function_count = obj.importedCountByKind(.function); + const type_index = obj.functions[symbol.index - import_function_count].type_index; + return obj.func_types[type_index]; } if (is_undefined) { const ty_index = self.imports.get(loc).?.kind.function; diff --git a/src/link/Wasm/Archive.zig b/src/link/Wasm/Archive.zig index 4a0abb1dfa..c80d26d17d 100644 --- a/src/link/Wasm/Archive.zig +++ b/src/link/Wasm/Archive.zig @@ -218,6 +218,7 @@ pub fn parseObject(archive: Archive, allocator: Allocator, file_offset: u32) !Ob const object_file = try std.fs.cwd().openFile(archive.name, .{}); errdefer object_file.close(); + const object_file_size = try header.size(); try object_file.seekTo(current_offset); - return Object.create(allocator, object_file, name); + return Object.create(allocator, object_file, name, object_file_size); } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index a1308ec045..50827ca9fb 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -105,14 +105,33 @@ pub const InitError = error{NotObjectFile} || ParseError || std.fs.File.ReadErro /// Initializes a new `Object` from a wasm object file. /// This also parses and verifies the object file. -pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8) InitError!Object { +/// When a max size is given, will only parse up to the given size, +/// else will read until the end of the file. +pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_size: ?usize) InitError!Object { var object: Object = .{ .file = file, .name = try gpa.dupe(u8, name), }; var is_object_file: bool = false; - try object.parse(gpa, file.reader(), &is_object_file); + const size = maybe_max_size orelse size: { + errdefer gpa.free(object.name); + const stat = try file.stat(); + break :size @intCast(usize, stat.size); + }; + + const file_contents = try gpa.alloc(u8, size); + defer gpa.free(file_contents); + var file_reader = file.reader(); + var read: usize = 0; + while (read < size) { + const n = try file_reader.read(file_contents[read..]); + std.debug.assert(n != 0); + read += n; + } + var fbs = std.io.fixedBufferStream(file_contents); + + try object.parse(gpa, fbs.reader(), &is_object_file); errdefer object.deinit(gpa); if (!is_object_file) return error.NotObjectFile;