| ... | ... | @@ -655,9 +655,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool { |
| 655 | 655 | errdefer obj_file.close(); |
| 656 | 656 | |
| 657 | 657 | const gpa = wasm.base.comp.gpa; |
| 658 | | var object = Object.create(gpa, obj_file, path, null) catch |err| switch (err) { |
| 658 | var object = Object.create(wasm, obj_file, path, null) catch |err| switch (err) { |
| 659 | 659 | error.InvalidMagicByte, error.NotObjectFile => return false, |
| 660 | | else => |e| return e, |
| 660 | else => |e| { |
| 661 | var err_note = try wasm.addErrorWithNotes(1); |
| 662 | try err_note.addMsg(wasm, "Failed parsing object file: {s}", .{@errorName(e)}); |
| 663 | try err_note.addNote(wasm, "while parsing '{s}'", .{path}); |
| 664 | return error.FlushFailure; |
| 665 | }, |
| 661 | 666 | }; |
| 662 | 667 | errdefer object.deinit(gpa); |
| 663 | 668 | object.index = @enumFromInt(wasm.files.len); |
| ... | ... | @@ -708,7 +713,12 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { |
| 708 | 713 | archive.deinit(gpa); |
| 709 | 714 | return false; |
| 710 | 715 | }, |
| 711 | | else => |e| return e, |
| 716 | else => |e| { |
| 717 | var err_note = try wasm.addErrorWithNotes(1); |
| 718 | try err_note.addMsg(wasm, "Failed parsing archive: {s}", .{@errorName(e)}); |
| 719 | try err_note.addNote(wasm, "while parsing archive {s}", .{path}); |
| 720 | return error.FlushFailure; |
| 721 | }, |
| 712 | 722 | }; |
| 713 | 723 | |
| 714 | 724 | if (!force_load) { |
| ... | ... | @@ -730,7 +740,12 @@ fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool { |
| 730 | 740 | } |
| 731 | 741 | |
| 732 | 742 | for (offsets.keys()) |file_offset| { |
| 733 | | var object = try archive.parseObject(gpa, file_offset); |
| 743 | var object = archive.parseObject(wasm, file_offset) catch |e| { |
| 744 | var err_note = try wasm.addErrorWithNotes(1); |
| 745 | try err_note.addMsg(wasm, "Failed parsing object: {s}", .{@errorName(e)}); |
| 746 | try err_note.addNote(wasm, "while parsing object in archive {s}", .{path}); |
| 747 | return error.FlushFailure; |
| 748 | }; |
| 734 | 749 | object.index = @enumFromInt(wasm.files.len); |
| 735 | 750 | try wasm.files.append(gpa, .{ .object = object }); |
| 736 | 751 | try wasm.objects.append(gpa, object.index); |
| ... | ... | @@ -764,9 +779,9 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 764 | 779 | |
| 765 | 780 | if (symbol.isLocal()) { |
| 766 | 781 | if (symbol.isUndefined()) { |
| 767 | | log.err("Local symbols are not allowed to reference imports", .{}); |
| 768 | | log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, obj_file.path() }); |
| 769 | | return error.UndefinedLocal; |
| 782 | var err = try wasm.addErrorWithNotes(1); |
| 783 | try err.addMsg(wasm, "Local symbols are not allowed to reference imports", .{}); |
| 784 | try err.addNote(wasm, "symbol '{s}' defined in '{s}'", .{ sym_name, obj_file.path() }); |
| 770 | 785 | } |
| 771 | 786 | try wasm.resolved_symbols.putNoClobber(gpa, location, {}); |
| 772 | 787 | continue; |
| ... | ... | @@ -801,10 +816,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 801 | 816 | break :outer; // existing is weak, while new one isn't. Replace it. |
| 802 | 817 | } |
| 803 | 818 | // both are defined and weak, we have a symbol collision. |
| 804 | | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 805 | | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 806 | | log.err(" next definition in '{s}'", .{obj_file.path()}); |
| 807 | | return error.SymbolCollision; |
| 819 | var err = try wasm.addErrorWithNotes(2); |
| 820 | try err.addMsg(wasm, "symbol '{s}' defined multiple times", .{sym_name}); |
| 821 | try err.addNote(wasm, "first definition in '{s}'", .{existing_file_path}); |
| 822 | try err.addNote(wasm, "next definition in '{s}'", .{obj_file.path()}); |
| 808 | 823 | } |
| 809 | 824 | |
| 810 | 825 | try wasm.discarded.put(gpa, location, existing_loc); |
| ... | ... | @@ -812,10 +827,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 812 | 827 | } |
| 813 | 828 | |
| 814 | 829 | if (symbol.tag != existing_sym.tag) { |
| 815 | | log.err("symbol '{s}' mismatching types '{s}' and '{s}'", .{ sym_name, @tagName(symbol.tag), @tagName(existing_sym.tag) }); |
| 816 | | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 817 | | log.err(" next definition in '{s}'", .{obj_file.path()}); |
| 818 | | return error.SymbolMismatchingType; |
| 830 | var err = try wasm.addErrorWithNotes(2); |
| 831 | try err.addMsg(wasm, "symbol '{s}' mismatching types '{s}' and '{s}'", .{ sym_name, @tagName(symbol.tag), @tagName(existing_sym.tag) }); |
| 832 | try err.addNote(wasm, "first definition in '{s}'", .{existing_file_path}); |
| 833 | try err.addNote(wasm, "next definition in '{s}'", .{obj_file.path()}); |
| 819 | 834 | } |
| 820 | 835 | |
| 821 | 836 | if (existing_sym.isUndefined() and symbol.isUndefined()) { |
| ... | ... | @@ -832,14 +847,14 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 832 | 847 | const imp = obj_file.import(sym_index); |
| 833 | 848 | const module_name = obj_file.string(imp.module_name); |
| 834 | 849 | if (!mem.eql(u8, existing_name, module_name)) { |
| 835 | | log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{ |
| 850 | var err = try wasm.addErrorWithNotes(2); |
| 851 | try err.addMsg(wasm, "symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{ |
| 836 | 852 | sym_name, |
| 837 | 853 | existing_name, |
| 838 | 854 | module_name, |
| 839 | 855 | }); |
| 840 | | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 841 | | log.err(" next definition in '{s}'", .{obj_file.path()}); |
| 842 | | return error.ModuleNameMismatch; |
| 856 | try err.addNote(wasm, "first definition in '{s}'", .{existing_file_path}); |
| 857 | try err.addNote(wasm, "next definition in '{s}'", .{obj_file.path()}); |
| 843 | 858 | } |
| 844 | 859 | } |
| 845 | 860 | |
| ... | ... | @@ -852,10 +867,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 852 | 867 | const existing_ty = wasm.getGlobalType(existing_loc); |
| 853 | 868 | const new_ty = wasm.getGlobalType(location); |
| 854 | 869 | if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) { |
| 855 | | log.err("symbol '{s}' mismatching global types", .{sym_name}); |
| 856 | | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 857 | | log.err(" next definition in '{s}'", .{obj_file.path()}); |
| 858 | | return error.GlobalTypeMismatch; |
| 870 | var err = try wasm.addErrorWithNotes(2); |
| 871 | try err.addMsg(wasm, "symbol '{s}' mismatching global types", .{sym_name}); |
| 872 | try err.addNote(wasm, "first definition in '{s}'", .{existing_file_path}); |
| 873 | try err.addNote(wasm, "next definition in '{s}'", .{obj_file.path()}); |
| 859 | 874 | } |
| 860 | 875 | } |
| 861 | 876 | |
| ... | ... | @@ -863,11 +878,11 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 863 | 878 | const existing_ty = wasm.getFunctionSignature(existing_loc); |
| 864 | 879 | const new_ty = wasm.getFunctionSignature(location); |
| 865 | 880 | if (!existing_ty.eql(new_ty)) { |
| 866 | | log.err("symbol '{s}' mismatching function signatures.", .{sym_name}); |
| 867 | | log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty }); |
| 868 | | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 869 | | log.err(" next definition in '{s}'", .{obj_file.path()}); |
| 870 | | return error.FunctionSignatureMismatch; |
| 881 | var err = try wasm.addErrorWithNotes(3); |
| 882 | try err.addMsg(wasm, "symbol '{s}' mismatching function signatures.", .{sym_name}); |
| 883 | try err.addNote(wasm, "expected signature {}, but found signature {}", .{ existing_ty, new_ty }); |
| 884 | try err.addNote(wasm, "first definition in '{s}'", .{existing_file_path}); |
| 885 | try err.addNote(wasm, "next definition in '{s}'", .{obj_file.path()}); |
| 871 | 886 | } |
| 872 | 887 | } |
| 873 | 888 | |
| ... | ... | @@ -914,7 +929,12 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void { |
| 914 | 929 | // Symbol is found in unparsed object file within current archive. |
| 915 | 930 | // Parse object and and resolve symbols again before we check remaining |
| 916 | 931 | // undefined symbols. |
| 917 | | var object = try archive.parseObject(gpa, offset.items[0]); |
| 932 | var object = archive.parseObject(wasm, offset.items[0]) catch |e| { |
| 933 | var err_note = try wasm.addErrorWithNotes(1); |
| 934 | try err_note.addMsg(wasm, "Failed parsing object: {s}", .{@errorName(e)}); |
| 935 | try err_note.addNote(wasm, "while parsing object in archive {s}", .{archive.name}); |
| 936 | return error.FlushFailure; |
| 937 | }; |
| 918 | 938 | object.index = @enumFromInt(wasm.files.len); |
| 919 | 939 | try wasm.files.append(gpa, .{ .object = object }); |
| 920 | 940 | try wasm.objects.append(gpa, object.index); |
| ... | ... | @@ -1214,20 +1234,21 @@ fn validateFeatures( |
| 1214 | 1234 | allowed[used_index] = is_enabled; |
| 1215 | 1235 | emit_features_count.* += @intFromBool(is_enabled); |
| 1216 | 1236 | } else if (is_enabled and !allowed[used_index]) { |
| 1217 | | log.err("feature '{}' not allowed, but used by linked object", .{@as(types.Feature.Tag, @enumFromInt(used_index))}); |
| 1218 | | log.err(" defined in '{s}'", .{wasm.files.items(.data)[used_set >> 1].object.path}); |
| 1237 | var err = try wasm.addErrorWithNotes(1); |
| 1238 | try err.addMsg(wasm, "feature '{}' not allowed, but used by linked object", .{@as(types.Feature.Tag, @enumFromInt(used_index))}); |
| 1239 | try err.addNote(wasm, "defined in '{s}'", .{wasm.files.items(.data)[used_set >> 1].object.path}); |
| 1219 | 1240 | valid_feature_set = false; |
| 1220 | 1241 | } |
| 1221 | 1242 | } |
| 1222 | 1243 | |
| 1223 | 1244 | if (!valid_feature_set) { |
| 1224 | | return error.InvalidFeatureSet; |
| 1245 | return error.FlushFailure; |
| 1225 | 1246 | } |
| 1226 | 1247 | |
| 1227 | 1248 | if (shared_memory) { |
| 1228 | 1249 | const disallowed_feature = disallowed[@intFromEnum(types.Feature.Tag.shared_mem)]; |
| 1229 | 1250 | if (@as(u1, @truncate(disallowed_feature)) != 0) { |
| 1230 | | log.err( |
| 1251 | try wasm.addErrorWithoutNotes( |
| 1231 | 1252 | "shared-memory is disallowed by '{s}' because it wasn't compiled with 'atomics' and 'bulk-memory' features enabled", |
| 1232 | 1253 | .{wasm.files.items(.data)[disallowed_feature >> 1].object.path}, |
| 1233 | 1254 | ); |
| ... | ... | @@ -1236,7 +1257,7 @@ fn validateFeatures( |
| 1236 | 1257 | |
| 1237 | 1258 | for ([_]types.Feature.Tag{ .atomics, .bulk_memory }) |feature| { |
| 1238 | 1259 | if (!allowed[@intFromEnum(feature)]) { |
| 1239 | | log.err("feature '{}' is not used but is required for shared-memory", .{feature}); |
| 1260 | try wasm.addErrorWithoutNotes("feature '{}' is not used but is required for shared-memory", .{feature}); |
| 1240 | 1261 | } |
| 1241 | 1262 | } |
| 1242 | 1263 | } |
| ... | ... | @@ -1244,7 +1265,7 @@ fn validateFeatures( |
| 1244 | 1265 | if (has_tls) { |
| 1245 | 1266 | for ([_]types.Feature.Tag{ .atomics, .bulk_memory }) |feature| { |
| 1246 | 1267 | if (!allowed[@intFromEnum(feature)]) { |
| 1247 | | log.err("feature '{}' is not used but is required for thread-local storage", .{feature}); |
| 1268 | try wasm.addErrorWithoutNotes("feature '{}' is not used but is required for thread-local storage", .{feature}); |
| 1248 | 1269 | } |
| 1249 | 1270 | } |
| 1250 | 1271 | } |
| ... | ... | @@ -1257,9 +1278,10 @@ fn validateFeatures( |
| 1257 | 1278 | // from here a feature is always used |
| 1258 | 1279 | const disallowed_feature = disallowed[@intFromEnum(feature.tag)]; |
| 1259 | 1280 | if (@as(u1, @truncate(disallowed_feature)) != 0) { |
| 1260 | | log.err("feature '{}' is disallowed, but used by linked object", .{feature.tag}); |
| 1261 | | log.err(" disallowed by '{s}'", .{wasm.files.items(.data)[disallowed_feature >> 1].object.path}); |
| 1262 | | log.err(" used in '{s}'", .{object.path}); |
| 1281 | var err = try wasm.addErrorWithNotes(2); |
| 1282 | try err.addMsg(wasm, "feature '{}' is disallowed, but used by linked object", .{feature.tag}); |
| 1283 | try err.addNote(wasm, "disallowed by '{s}'", .{wasm.files.items(.data)[disallowed_feature >> 1].object.path}); |
| 1284 | try err.addNote(wasm, "used in '{s}'", .{object.path}); |
| 1263 | 1285 | valid_feature_set = false; |
| 1264 | 1286 | } |
| 1265 | 1287 | |
| ... | ... | @@ -1270,16 +1292,17 @@ fn validateFeatures( |
| 1270 | 1292 | for (required, 0..) |required_feature, feature_index| { |
| 1271 | 1293 | const is_required = @as(u1, @truncate(required_feature)) != 0; |
| 1272 | 1294 | if (is_required and !object_used_features[feature_index]) { |
| 1273 | | log.err("feature '{}' is required but not used in linked object", .{@as(types.Feature.Tag, @enumFromInt(feature_index))}); |
| 1274 | | log.err(" required by '{s}'", .{wasm.files.items(.data)[required_feature >> 1].object.path}); |
| 1275 | | log.err(" missing in '{s}'", .{object.path}); |
| 1295 | var err = try wasm.addErrorWithNotes(2); |
| 1296 | try err.addMsg(wasm, "feature '{}' is required but not used in linked object", .{@as(types.Feature.Tag, @enumFromInt(feature_index))}); |
| 1297 | try err.addNote(wasm, "required by '{s}'", .{wasm.files.items(.data)[required_feature >> 1].object.path}); |
| 1298 | try err.addNote(wasm, "missing in '{s}'", .{object.path}); |
| 1276 | 1299 | valid_feature_set = false; |
| 1277 | 1300 | } |
| 1278 | 1301 | } |
| 1279 | 1302 | } |
| 1280 | 1303 | |
| 1281 | 1304 | if (!valid_feature_set) { |
| 1282 | | return error.InvalidFeatureSet; |
| 1305 | return error.FlushFailure; |
| 1283 | 1306 | } |
| 1284 | 1307 | |
| 1285 | 1308 | to_emit.* = allowed; |
| ... | ... | @@ -1350,12 +1373,13 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void { |
| 1350 | 1373 | else |
| 1351 | 1374 | wasm.name; |
| 1352 | 1375 | const symbol_name = undef.getName(wasm); |
| 1353 | | log.err("could not resolve undefined symbol '{s}'", .{symbol_name}); |
| 1354 | | log.err(" defined in '{s}'", .{file_name}); |
| 1376 | var err = try wasm.addErrorWithNotes(1); |
| 1377 | try err.addMsg(wasm, "could not resolve undefined symbol '{s}'", .{symbol_name}); |
| 1378 | try err.addNote(wasm, "defined in '{s}'", .{file_name}); |
| 1355 | 1379 | } |
| 1356 | 1380 | } |
| 1357 | 1381 | if (found_undefined_symbols) { |
| 1358 | | return error.UndefinedSymbol; |
| 1382 | return error.FlushFailure; |
| 1359 | 1383 | } |
| 1360 | 1384 | } |
| 1361 | 1385 | |
| ... | ... | @@ -1728,8 +1752,7 @@ fn setupInitFunctions(wasm: *Wasm) !void { |
| 1728 | 1752 | break :ty object.func_types[func.type_index]; |
| 1729 | 1753 | }; |
| 1730 | 1754 | if (ty.params.len != 0) { |
| 1731 | | log.err("constructor functions cannot take arguments: '{s}'", .{object.string_table.get(symbol.name)}); |
| 1732 | | return error.InvalidInitFunc; |
| 1755 | try wasm.addErrorWithoutNotes("constructor functions cannot take arguments: '{s}'", .{object.string_table.get(symbol.name)}); |
| 1733 | 1756 | } |
| 1734 | 1757 | log.debug("appended init func '{s}'\n", .{object.string_table.get(symbol.name)}); |
| 1735 | 1758 | wasm.init_funcs.appendAssumeCapacity(.{ |
| ... | ... | @@ -2108,7 +2131,7 @@ fn setupExports(wasm: *Wasm) !void { |
| 2108 | 2131 | |
| 2109 | 2132 | for (force_exp_names) |exp_name| { |
| 2110 | 2133 | const loc = wasm.findGlobalSymbol(exp_name) orelse { |
| 2111 | | log.err("could not export '{s}', symbol not found", .{exp_name}); |
| 2134 | try wasm.addErrorWithoutNotes("could not export '{s}', symbol not found", .{exp_name}); |
| 2112 | 2135 | failed_exports = true; |
| 2113 | 2136 | continue; |
| 2114 | 2137 | }; |
| ... | ... | @@ -2118,7 +2141,7 @@ fn setupExports(wasm: *Wasm) !void { |
| 2118 | 2141 | } |
| 2119 | 2142 | |
| 2120 | 2143 | if (failed_exports) { |
| 2121 | | return error.MissingSymbol; |
| 2144 | return error.FlushFailure; |
| 2122 | 2145 | } |
| 2123 | 2146 | } |
| 2124 | 2147 | |
| ... | ... | @@ -2164,14 +2187,14 @@ fn setupStart(wasm: *Wasm) !void { |
| 2164 | 2187 | const entry_name = wasm.entry_name orelse return; |
| 2165 | 2188 | |
| 2166 | 2189 | const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { |
| 2167 | | log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); |
| 2168 | | return error.MissingSymbol; |
| 2190 | try wasm.addErrorWithoutNotes("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); |
| 2191 | return error.FlushFailure; |
| 2169 | 2192 | }; |
| 2170 | 2193 | |
| 2171 | 2194 | const symbol = symbol_loc.getSymbol(wasm); |
| 2172 | 2195 | if (symbol.tag != .function) { |
| 2173 | | log.err("Entry symbol '{s}' is not a function", .{entry_name}); |
| 2174 | | return error.InvalidEntryKind; |
| 2196 | try wasm.addErrorWithoutNotes("Entry symbol '{s}' is not a function", .{entry_name}); |
| 2197 | return error.FlushFailure; |
| 2175 | 2198 | } |
| 2176 | 2199 | |
| 2177 | 2200 | // Ensure the symbol is exported so host environment can access it |
| ... | ... | @@ -2274,16 +2297,13 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2274 | 2297 | |
| 2275 | 2298 | if (wasm.initial_memory) |initial_memory| { |
| 2276 | 2299 | if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) { |
| 2277 | | log.err("Initial memory must be {d}-byte aligned", .{page_size}); |
| 2278 | | return error.MissAlignment; |
| 2300 | try wasm.addErrorWithoutNotes("Initial memory must be {d}-byte aligned", .{page_size}); |
| 2279 | 2301 | } |
| 2280 | 2302 | if (memory_ptr > initial_memory) { |
| 2281 | | log.err("Initial memory too small, must be at least {d} bytes", .{memory_ptr}); |
| 2282 | | return error.MemoryTooSmall; |
| 2303 | try wasm.addErrorWithoutNotes("Initial memory too small, must be at least {d} bytes", .{memory_ptr}); |
| 2283 | 2304 | } |
| 2284 | 2305 | if (initial_memory > max_memory_allowed) { |
| 2285 | | log.err("Initial memory exceeds maximum memory {d}", .{max_memory_allowed}); |
| 2286 | | return error.MemoryTooBig; |
| 2306 | try wasm.addErrorWithoutNotes("Initial memory exceeds maximum memory {d}", .{max_memory_allowed}); |
| 2287 | 2307 | } |
| 2288 | 2308 | memory_ptr = initial_memory; |
| 2289 | 2309 | } |
| ... | ... | @@ -2300,16 +2320,13 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2300 | 2320 | |
| 2301 | 2321 | if (wasm.max_memory) |max_memory| { |
| 2302 | 2322 | if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) { |
| 2303 | | log.err("Maximum memory must be {d}-byte aligned", .{page_size}); |
| 2304 | | return error.MissAlignment; |
| 2323 | try wasm.addErrorWithoutNotes("Maximum memory must be {d}-byte aligned", .{page_size}); |
| 2305 | 2324 | } |
| 2306 | 2325 | if (memory_ptr > max_memory) { |
| 2307 | | log.err("Maxmimum memory too small, must be at least {d} bytes", .{memory_ptr}); |
| 2308 | | return error.MemoryTooSmall; |
| 2326 | try wasm.addErrorWithoutNotes("Maxmimum memory too small, must be at least {d} bytes", .{memory_ptr}); |
| 2309 | 2327 | } |
| 2310 | 2328 | if (max_memory > max_memory_allowed) { |
| 2311 | | log.err("Maximum memory exceeds maxmium amount {d}", .{max_memory_allowed}); |
| 2312 | | return error.MemoryTooBig; |
| 2329 | try wasm.addErrorWithoutNotes("Maximum memory exceeds maxmium amount {d}", .{max_memory_allowed}); |
| 2313 | 2330 | } |
| 2314 | 2331 | wasm.memories.limits.max = @as(u32, @intCast(max_memory / page_size)); |
| 2315 | 2332 | wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_HAS_MAX); |
| ... | ... | @@ -2412,7 +2429,9 @@ pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: Sym |
| 2412 | 2429 | break :blk index; |
| 2413 | 2430 | }; |
| 2414 | 2431 | } else { |
| 2415 | | log.err("found unknown section '{s}'", .{section_name}); |
| 2432 | var err = try wasm.addErrorWithNotes(1); |
| 2433 | try err.addMsg(wasm, "found unknown section '{s}'", .{section_name}); |
| 2434 | try err.addNote(wasm, "defined in '{s}'", .{obj_file.path()}); |
| 2416 | 2435 | return error.UnexpectedValue; |
| 2417 | 2436 | } |
| 2418 | 2437 | }, |
| ... | ... | @@ -2529,18 +2548,22 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 2529 | 2548 | if (wasm.zig_object_index != .null) { |
| 2530 | 2549 | try wasm.resolveSymbolsInObject(wasm.zig_object_index); |
| 2531 | 2550 | } |
| 2551 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2532 | 2552 | for (wasm.objects.items) |object_index| { |
| 2533 | 2553 | try wasm.resolveSymbolsInObject(object_index); |
| 2534 | 2554 | } |
| 2555 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2535 | 2556 | |
| 2536 | 2557 | var emit_features_count: u32 = 0; |
| 2537 | 2558 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; |
| 2538 | 2559 | try wasm.validateFeatures(&enabled_features, &emit_features_count); |
| 2539 | 2560 | try wasm.resolveSymbolsInArchives(); |
| 2561 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2540 | 2562 | try wasm.resolveLazySymbols(); |
| 2541 | 2563 | try wasm.checkUndefinedSymbols(); |
| 2542 | 2564 | |
| 2543 | 2565 | try wasm.setupInitFunctions(); |
| 2566 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2544 | 2567 | try wasm.setupStart(); |
| 2545 | 2568 | |
| 2546 | 2569 | try wasm.markReferences(); |
| ... | ... | @@ -2549,6 +2572,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 2549 | 2572 | try wasm.mergeTypes(); |
| 2550 | 2573 | try wasm.allocateAtoms(); |
| 2551 | 2574 | try wasm.setupMemory(); |
| 2575 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2552 | 2576 | wasm.allocateVirtualAddresses(); |
| 2553 | 2577 | wasm.mapFunctionTable(); |
| 2554 | 2578 | try wasm.initializeCallCtorsFunction(); |
| ... | ... | @@ -2558,6 +2582,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) |
| 2558 | 2582 | try wasm.setupStartSection(); |
| 2559 | 2583 | try wasm.setupExports(); |
| 2560 | 2584 | try wasm.writeToFile(enabled_features, emit_features_count, arena); |
| 2585 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 2561 | 2586 | } |
| 2562 | 2587 | |
| 2563 | 2588 | /// Writes the WebAssembly in-memory module to the file |
| ... | ... | @@ -2955,7 +2980,7 @@ fn writeToFile( |
| 2955 | 2980 | }) catch unreachable; |
| 2956 | 2981 | try emitBuildIdSection(&binary_bytes, str); |
| 2957 | 2982 | }, |
| 2958 | | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), |
| 2983 | else => |mode| try wasm.addErrorWithoutNotes("build-id '{s}' is not supported for WebAssembly", .{@tagName(mode)}), |
| 2959 | 2984 | } |
| 2960 | 2985 | |
| 2961 | 2986 | var debug_bytes = std.ArrayList(u8).init(gpa); |
| ... | ... | @@ -4043,3 +4068,57 @@ fn defaultEntrySymbolName(wasi_exec_model: std.builtin.WasiExecModel) []const u8 |
| 4043 | 4068 | .command => "_start", |
| 4044 | 4069 | }; |
| 4045 | 4070 | } |
| 4071 | |
| 4072 | const ErrorWithNotes = struct { |
| 4073 | /// Allocated index in comp.link_errors array. |
| 4074 | index: usize, |
| 4075 | |
| 4076 | /// Next available note slot. |
| 4077 | note_slot: usize = 0, |
| 4078 | |
| 4079 | pub fn addMsg( |
| 4080 | err: ErrorWithNotes, |
| 4081 | wasm_file: *const Wasm, |
| 4082 | comptime format: []const u8, |
| 4083 | args: anytype, |
| 4084 | ) error{OutOfMemory}!void { |
| 4085 | const comp = wasm_file.base.comp; |
| 4086 | const gpa = comp.gpa; |
| 4087 | const err_msg = &comp.link_errors.items[err.index]; |
| 4088 | err_msg.msg = try std.fmt.allocPrint(gpa, format, args); |
| 4089 | } |
| 4090 | |
| 4091 | pub fn addNote( |
| 4092 | err: *ErrorWithNotes, |
| 4093 | wasm_file: *const Wasm, |
| 4094 | comptime format: []const u8, |
| 4095 | args: anytype, |
| 4096 | ) error{OutOfMemory}!void { |
| 4097 | const comp = wasm_file.base.comp; |
| 4098 | const gpa = comp.gpa; |
| 4099 | const err_msg = &comp.link_errors.items[err.index]; |
| 4100 | err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; |
| 4101 | err.note_slot += 1; |
| 4102 | } |
| 4103 | }; |
| 4104 | |
| 4105 | pub fn addErrorWithNotes(wasm: *const Wasm, note_count: usize) error{OutOfMemory}!ErrorWithNotes { |
| 4106 | const comp = wasm.base.comp; |
| 4107 | const gpa = comp.gpa; |
| 4108 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); |
| 4109 | return wasm.addErrorWithNotesAssumeCapacity(note_count); |
| 4110 | } |
| 4111 | |
| 4112 | pub fn addErrorWithoutNotes(wasm: *const Wasm, comptime fmt: []const u8, args: anytype) !void { |
| 4113 | const err = try wasm.addErrorWithNotes(0); |
| 4114 | try err.addMsg(wasm, fmt, args); |
| 4115 | } |
| 4116 | |
| 4117 | fn addErrorWithNotesAssumeCapacity(wasm: *const Wasm, note_count: usize) error{OutOfMemory}!ErrorWithNotes { |
| 4118 | const comp = wasm.base.comp; |
| 4119 | const gpa = comp.gpa; |
| 4120 | const index = comp.link_errors.items.len; |
| 4121 | const err = comp.link_errors.addOneAssumeCapacity(); |
| 4122 | err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; |
| 4123 | return .{ .index = index }; |
| 4124 | } |