authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-01-19 18:04:06+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-02-29 15:23:03+01:00
logcbc8d330622c597527397d98b14b6d298b1b981e
tree0b71f8c3bea3fdb9138c44b0ff1f99e6d7a4c4b2
parent143e9599d64e7ac7991f360679a5611ee0d59376
signaturelock-open Commit is signed but in an unrecognized format.

wasm: fix symbol resolution and atom processing


4 files changed, 89 insertions(+), 84 deletions(-)

src/link/Wasm.zig+55-52
...@@ -226,8 +226,8 @@ pub const SymbolLoc = struct {...@@ -226,8 +226,8 @@ pub const SymbolLoc = struct {
226 return new_loc.getSymbol(wasm_file);226 return new_loc.getSymbol(wasm_file);
227 }227 }
228 if (loc.file) |object_index| {228 if (loc.file) |object_index| {
229 const object = wasm_file.objects.items[object_index];229 const obj_file = wasm_file.file(@enumFromInt(object_index)).?;
230 return &object.symtable[loc.index];230 return obj_file.symbol(loc.index);
231 }231 }
232 return &wasm_file.synthetic_symbols.items[loc.index];232 return &wasm_file.synthetic_symbols.items[loc.index];
233 }233 }
...@@ -238,8 +238,8 @@ pub const SymbolLoc = struct {...@@ -238,8 +238,8 @@ pub const SymbolLoc = struct {
238 return new_loc.getName(wasm_file);238 return new_loc.getName(wasm_file);
239 }239 }
240 if (loc.file) |object_index| {240 if (loc.file) |object_index| {
241 const object = wasm_file.objects.items[object_index];241 const obj_file = wasm_file.file(@enumFromInt(object_index)).?;
242 return object.string_table.get(object.symtable[loc.index].name);242 return obj_file.symbolName(loc.index);
243 }243 }
244 return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name);244 return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name);
245 }245 }
...@@ -581,12 +581,13 @@ pub fn createEmpty(...@@ -581,12 +581,13 @@ pub fn createEmpty(
581 return wasm;581 return wasm;
582}582}
583583
584pub fn file(wasm: *Wasm, index: File.Index) ?File {584pub fn file(wasm: *const Wasm, index: File.Index) ?File {
585 const tag = wasm.files.items(.tags)[index];585 if (index == .null) return null;
586 const tag = wasm.files.items(.tags)[@intFromEnum(index)];
586 return switch (tag) {587 return switch (tag) {
587 .null => null,588 .null => null,
588 .zig_object => .{ .zig_object = &wasm.files.items(.data)[index].zig_object },589 .zig_object => .{ .zig_object = &wasm.files.items(.data)[@intFromEnum(index)].zig_object },
589 .object => .{ .object = &wasm.files.items(.data)[index].object },590 .object => .{ .object = &wasm.files.items(.data)[@intFromEnum(index)].object },
590 };591 };
591}592}
592593
...@@ -678,7 +679,7 @@ pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Ind...@@ -678,7 +679,7 @@ pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Ind
678 const gpa = wasm.base.comp.gpa;679 const gpa = wasm.base.comp.gpa;
679 const index: Atom.Index = @intCast(wasm.managed_atoms.items.len);680 const index: Atom.Index = @intCast(wasm.managed_atoms.items.len);
680 const atom = try wasm.managed_atoms.addOne(gpa);681 const atom = try wasm.managed_atoms.addOne(gpa);
681 atom.* = .{ .file_index = file_index, .sym_index = sym_index };682 atom.* = .{ .file = file_index, .sym_index = sym_index };
682 try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = sym_index }, index);683 try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = sym_index }, index);
683684
684 return index;685 return index;
...@@ -755,18 +756,18 @@ fn requiresTLSReloc(wasm: *const Wasm) bool {...@@ -755,18 +756,18 @@ fn requiresTLSReloc(wasm: *const Wasm) bool {
755 return false;756 return false;
756}757}
757758
758fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {759fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void {
759 const gpa = wasm.base.comp.gpa;760 const gpa = wasm.base.comp.gpa;
760 const object: Object = wasm.objects.items[object_index];761 const obj_file = wasm.file(file_index).?;
761 log.debug("Resolving symbols in object: '{s}'", .{object.name});762 log.debug("Resolving symbols in object: '{s}'", .{obj_file.path()});
762763
763 for (object.symtable, 0..) |symbol, i| {764 for (obj_file.symbols(), 0..) |symbol, i| {
764 const sym_index = @as(u32, @intCast(i));765 const sym_index: u32 = @intCast(i);
765 const location: SymbolLoc = .{766 const location: SymbolLoc = .{
766 .file = object_index,767 .file = @intFromEnum(file_index),
767 .index = sym_index,768 .index = sym_index,
768 };769 };
769 const sym_name = object.string_table.get(symbol.name);770 const sym_name = obj_file.string(symbol.name);
770 if (mem.eql(u8, sym_name, "__indirect_function_table")) {771 if (mem.eql(u8, sym_name, "__indirect_function_table")) {
771 continue;772 continue;
772 }773 }
...@@ -775,7 +776,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -775,7 +776,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
775 if (symbol.isLocal()) {776 if (symbol.isLocal()) {
776 if (symbol.isUndefined()) {777 if (symbol.isUndefined()) {
777 log.err("Local symbols are not allowed to reference imports", .{});778 log.err("Local symbols are not allowed to reference imports", .{});
778 log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name });779 log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, obj_file.path() });
779 return error.UndefinedLocal;780 return error.UndefinedLocal;
780 }781 }
781 try wasm.resolved_symbols.putNoClobber(gpa, location, {});782 try wasm.resolved_symbols.putNoClobber(gpa, location, {});
...@@ -796,9 +797,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -796,9 +797,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
796 const existing_loc = maybe_existing.value_ptr.*;797 const existing_loc = maybe_existing.value_ptr.*;
797 const existing_sym: *Symbol = existing_loc.getSymbol(wasm);798 const existing_sym: *Symbol = existing_loc.getSymbol(wasm);
798799
799 const existing_file_path = if (existing_loc.file) |file_index| blk: {800 const existing_file_path = if (existing_loc.file) |existing_file_index|
800 break :blk wasm.objects.items[file_index].name;801 wasm.file(@enumFromInt(existing_file_index)).?.path()
801 } else wasm.name;802 else
803 wasm.name;
802804
803 if (!existing_sym.isUndefined()) outer: {805 if (!existing_sym.isUndefined()) outer: {
804 if (!symbol.isUndefined()) inner: {806 if (!symbol.isUndefined()) inner: {
...@@ -811,7 +813,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -811,7 +813,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
811 // both are defined and weak, we have a symbol collision.813 // both are defined and weak, we have a symbol collision.
812 log.err("symbol '{s}' defined multiple times", .{sym_name});814 log.err("symbol '{s}' defined multiple times", .{sym_name});
813 log.err(" first definition in '{s}'", .{existing_file_path});815 log.err(" first definition in '{s}'", .{existing_file_path});
814 log.err(" next definition in '{s}'", .{object.name});816 log.err(" next definition in '{s}'", .{obj_file.path()});
815 return error.SymbolCollision;817 return error.SymbolCollision;
816 }818 }
817819
...@@ -822,24 +824,24 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -822,24 +824,24 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
822 if (symbol.tag != existing_sym.tag) {824 if (symbol.tag != existing_sym.tag) {
823 log.err("symbol '{s}' mismatching type '{s}", .{ sym_name, @tagName(symbol.tag) });825 log.err("symbol '{s}' mismatching type '{s}", .{ sym_name, @tagName(symbol.tag) });
824 log.err(" first definition in '{s}'", .{existing_file_path});826 log.err(" first definition in '{s}'", .{existing_file_path});
825 log.err(" next definition in '{s}'", .{object.name});827 log.err(" next definition in '{s}'", .{obj_file.path()});
826 return error.SymbolMismatchingType;828 return error.SymbolMismatchingType;
827 }829 }
828830
829 if (existing_sym.isUndefined() and symbol.isUndefined()) {831 if (existing_sym.isUndefined() and symbol.isUndefined()) {
830 // only verify module/import name for function symbols832 // only verify module/import name for function symbols
831 if (symbol.tag == .function) {833 if (symbol.tag == .function) {
832 const existing_name = if (existing_loc.file) |file_index| blk: {834 const existing_name = if (existing_loc.file) |existing_file_index| blk: {
833 const obj = wasm.objects.items[file_index];835 const existing_obj = wasm.file(@enumFromInt(existing_file_index)).?;
834 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;836 const imp = existing_obj.import(existing_loc.index);
835 break :blk obj.string_table.get(name_index);837 break :blk existing_obj.string(imp.module_name);
836 } else blk: {838 } else blk: {
837 const name_index = wasm.imports.get(existing_loc).?.module_name;839 const name_index = wasm.imports.get(existing_loc).?.module_name;
838 break :blk wasm.string_table.get(name_index);840 break :blk wasm.string_table.get(name_index);
839 };841 };
840842
841 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;843 const imp = obj_file.import(sym_index);
842 const module_name = object.string_table.get(module_index);844 const module_name = obj_file.string(imp.module_name);
843 if (!mem.eql(u8, existing_name, module_name)) {845 if (!mem.eql(u8, existing_name, module_name)) {
844 log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{846 log.err("symbol '{s}' module name mismatch. Expected '{s}', but found '{s}'", .{
845 sym_name,847 sym_name,
...@@ -847,7 +849,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -847,7 +849,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
847 module_name,849 module_name,
848 });850 });
849 log.err(" first definition in '{s}'", .{existing_file_path});851 log.err(" first definition in '{s}'", .{existing_file_path});
850 log.err(" next definition in '{s}'", .{object.name});852 log.err(" next definition in '{s}'", .{obj_file.path()});
851 return error.ModuleNameMismatch;853 return error.ModuleNameMismatch;
852 }854 }
853 }855 }
...@@ -863,7 +865,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -863,7 +865,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
863 if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) {865 if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) {
864 log.err("symbol '{s}' mismatching global types", .{sym_name});866 log.err("symbol '{s}' mismatching global types", .{sym_name});
865 log.err(" first definition in '{s}'", .{existing_file_path});867 log.err(" first definition in '{s}'", .{existing_file_path});
866 log.err(" next definition in '{s}'", .{object.name});868 log.err(" next definition in '{s}'", .{obj_file.path()});
867 return error.GlobalTypeMismatch;869 return error.GlobalTypeMismatch;
868 }870 }
869 }871 }
...@@ -875,7 +877,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -875,7 +877,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
875 log.err("symbol '{s}' mismatching function signatures.", .{sym_name});877 log.err("symbol '{s}' mismatching function signatures.", .{sym_name});
876 log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty });878 log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty });
877 log.err(" first definition in '{s}'", .{existing_file_path});879 log.err(" first definition in '{s}'", .{existing_file_path});
878 log.err(" next definition in '{s}'", .{object.name});880 log.err(" next definition in '{s}'", .{obj_file.path()});
879 return error.FunctionSignatureMismatch;881 return error.FunctionSignatureMismatch;
880 }882 }
881 }883 }
...@@ -891,7 +893,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -891,7 +893,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
891 // simply overwrite with the new symbol893 // simply overwrite with the new symbol
892 log.debug("Overwriting symbol '{s}'", .{sym_name});894 log.debug("Overwriting symbol '{s}'", .{sym_name});
893 log.debug(" old definition in '{s}'", .{existing_file_path});895 log.debug(" old definition in '{s}'", .{existing_file_path});
894 log.debug(" new definition in '{s}'", .{object.name});896 log.debug(" new definition in '{s}'", .{obj_file.path()});
895 try wasm.discarded.putNoClobber(gpa, existing_loc, location);897 try wasm.discarded.putNoClobber(gpa, existing_loc, location);
896 maybe_existing.value_ptr.* = location;898 maybe_existing.value_ptr.* = location;
897 try wasm.globals.put(gpa, sym_name_index, location);899 try wasm.globals.put(gpa, sym_name_index, location);
...@@ -1190,7 +1192,7 @@ fn validateFeatures(...@@ -1190,7 +1192,7 @@ fn validateFeatures(
1190 // extract all the used, disallowed and required features from each1192 // extract all the used, disallowed and required features from each
1191 // linked object file so we can test them.1193 // linked object file so we can test them.
1192 for (wasm.objects.items) |file_index| {1194 for (wasm.objects.items) |file_index| {
1193 const object: Object = wasm.files.items(.data)[file_index].object;1195 const object: Object = wasm.files.items(.data)[@intFromEnum(file_index)].object;
1194 for (object.features) |feature| {1196 for (object.features) |feature| {
1195 const value = @as(u16, @intFromEnum(file_index)) << 1 | @as(u1, 1);1197 const value = @as(u16, @intFromEnum(file_index)) << 1 | @as(u1, 1);
1196 switch (feature.prefix) {1198 switch (feature.prefix) {
...@@ -1260,7 +1262,7 @@ fn validateFeatures(...@@ -1260,7 +1262,7 @@ fn validateFeatures(
1260 // For each linked object, validate the required and disallowed features1262 // For each linked object, validate the required and disallowed features
1261 for (wasm.objects.items) |file_index| {1263 for (wasm.objects.items) |file_index| {
1262 var object_used_features = [_]bool{false} ** known_features_count;1264 var object_used_features = [_]bool{false} ** known_features_count;
1263 const object = wasm.files.items(.data)[file_index].object;1265 const object = wasm.files.items(.data)[@intFromEnum(file_index)].object;
1264 for (object.features) |feature| {1266 for (object.features) |feature| {
1265 if (feature.prefix == .disallowed) continue; // already defined in 'disallowed' set.1267 if (feature.prefix == .disallowed) continue; // already defined in 'disallowed' set.
1266 // from here a feature is always used1268 // from here a feature is always used
...@@ -1362,7 +1364,7 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void {...@@ -1362,7 +1364,7 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void {
1362 if (symbol.tag == .data) {1364 if (symbol.tag == .data) {
1363 found_undefined_symbols = true;1365 found_undefined_symbols = true;
1364 const file_name = if (undef.file) |file_index|1366 const file_name = if (undef.file) |file_index|
1365 wasm.file(file_index).?.path()1367 wasm.file(@enumFromInt(file_index)).?.path()
1366 else1368 else
1367 wasm.name;1369 wasm.name;
1368 const symbol_name = undef.getName(wasm);1370 const symbol_name = undef.getName(wasm);
...@@ -1386,7 +1388,7 @@ pub fn deinit(wasm: *Wasm) void {...@@ -1386,7 +1388,7 @@ pub fn deinit(wasm: *Wasm) void {
1386 gpa.free(segment_info.name);1388 gpa.free(segment_info.name);
1387 }1389 }
1388 if (wasm.zigObjectPtr()) |zig_obj| {1390 if (wasm.zigObjectPtr()) |zig_obj| {
1389 zig_obj.deinit(gpa);1391 zig_obj.deinit(wasm);
1390 }1392 }
1391 for (wasm.objects.items) |obj_index| {1393 for (wasm.objects.items) |obj_index| {
1392 wasm.file(obj_index).?.object.deinit(gpa);1394 wasm.file(obj_index).?.object.deinit(gpa);
...@@ -1623,8 +1625,8 @@ fn allocateAtoms(wasm: *Wasm) !void {...@@ -1623,8 +1625,8 @@ fn allocateAtoms(wasm: *Wasm) !void {
1623 // Ensure we get the original symbol, so we verify the correct symbol on whether1625 // Ensure we get the original symbol, so we verify the correct symbol on whether
1624 // it is dead or not and ensure an atom is removed when dead.1626 // it is dead or not and ensure an atom is removed when dead.
1625 // This is required as we may have parsed aliases into atoms.1627 // This is required as we may have parsed aliases into atoms.
1626 const sym = if (symbol_loc.file) |object_index|1628 const sym = if (symbol_loc.file) |file_index|
1627 wasm.file(object_index).?.symbol(symbol_loc.index).*1629 wasm.file(@enumFromInt(file_index)).?.symbol(symbol_loc.index).*
1628 else1630 else
1629 wasm.synthetic_symbols.items[symbol_loc.index];1631 wasm.synthetic_symbols.items[symbol_loc.index];
16301632
...@@ -1672,8 +1674,8 @@ fn allocateVirtualAddresses(wasm: *Wasm) void {...@@ -1672,8 +1674,8 @@ fn allocateVirtualAddresses(wasm: *Wasm) void {
16721674
1673 const atom = wasm.getAtom(atom_index);1675 const atom = wasm.getAtom(atom_index);
1674 const merge_segment = wasm.base.comp.config.output_mode != .Obj;1676 const merge_segment = wasm.base.comp.config.output_mode != .Obj;
1675 const segment_info = if (atom.file) |object_index|1677 const segment_info = if (atom.file != .null)
1676 wasm.file(object_index).?.segmentInfo()1678 wasm.file(atom.file).?.segmentInfo()
1677 else1679 else
1678 wasm.segment_info.values();1680 wasm.segment_info.values();
1679 const segment_name = segment_info[symbol.index].outputName(merge_segment);1681 const segment_name = segment_info[symbol.index].outputName(merge_segment);
...@@ -1731,16 +1733,17 @@ fn sortDataSegments(wasm: *Wasm) !void {...@@ -1731,16 +1733,17 @@ fn sortDataSegments(wasm: *Wasm) !void {
1731/// contain any parameters.1733/// contain any parameters.
1732fn setupInitFunctions(wasm: *Wasm) !void {1734fn setupInitFunctions(wasm: *Wasm) !void {
1733 const gpa = wasm.base.comp.gpa;1735 const gpa = wasm.base.comp.gpa;
1736 // There's no constructors for Zig so we can simply search through linked object files only.
1734 for (wasm.objects.items) |file_index| {1737 for (wasm.objects.items) |file_index| {
1735 const object = wasm.files.items(.data)[file_index].object;1738 const object: Object = wasm.files.items(.data)[@intFromEnum(file_index)].object;
1736 try wasm.init_funcs.ensureUnusedCapacity(gpa, object.init_funcs.len);1739 try wasm.init_funcs.ensureUnusedCapacity(gpa, object.init_funcs.len);
1737 for (object.init_funcs) |init_func| {1740 for (object.init_funcs) |init_func| {
1738 const symbol = object.symtable[init_func.symbol_index];1741 const symbol = object.symtable[init_func.symbol_index];
1739 const ty: std.wasm.Type = if (symbol.isUndefined()) ty: {1742 const ty: std.wasm.Type = if (symbol.isUndefined()) ty: {
1740 const imp: types.Import = object.findImport(.function, symbol.index);1743 const imp: types.Import = object.findImport(symbol);
1741 break :ty object.func_types[imp.kind.function];1744 break :ty object.func_types[imp.kind.function];
1742 } else ty: {1745 } else ty: {
1743 const func_index = symbol.index - object.importedCountByKind(.function);1746 const func_index = symbol.index - object.imported_functions_count;
1744 const func = object.functions[func_index];1747 const func = object.functions[func_index];
1745 break :ty object.func_types[func.type_index];1748 break :ty object.func_types[func.type_index];
1746 };1749 };
...@@ -1751,10 +1754,10 @@ fn setupInitFunctions(wasm: *Wasm) !void {...@@ -1751,10 +1754,10 @@ fn setupInitFunctions(wasm: *Wasm) !void {
1751 log.debug("appended init func '{s}'\n", .{object.string_table.get(symbol.name)});1754 log.debug("appended init func '{s}'\n", .{object.string_table.get(symbol.name)});
1752 wasm.init_funcs.appendAssumeCapacity(.{1755 wasm.init_funcs.appendAssumeCapacity(.{
1753 .index = init_func.symbol_index,1756 .index = init_func.symbol_index,
1754 .file = @as(u16, @intCast(file_index)),1757 .file = @intFromEnum(file_index),
1755 .priority = init_func.priority,1758 .priority = init_func.priority,
1756 });1759 });
1757 try wasm.mark(.{ .index = init_func.symbol_index, .file = @intCast(file_index) });1760 try wasm.mark(.{ .index = init_func.symbol_index, .file = @intFromEnum(file_index) });
1758 }1761 }
1759 }1762 }
17601763
...@@ -1993,7 +1996,7 @@ fn setupImports(wasm: *Wasm) !void {...@@ -1993,7 +1996,7 @@ fn setupImports(wasm: *Wasm) !void {
1993 }1996 }
19941997
1995 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)});1998 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)});
1996 const obj_file = wasm.file(file_index).?;1999 const obj_file = wasm.file(@enumFromInt(file_index)).?;
1997 const import = obj_file.import(symbol_loc.index);2000 const import = obj_file.import(symbol_loc.index);
19982001
1999 // We copy the import to a new import to ensure the names contain references2002 // We copy the import to a new import to ensure the names contain references
...@@ -2058,7 +2061,7 @@ fn mergeSections(wasm: *Wasm) !void {...@@ -2058,7 +2061,7 @@ fn mergeSections(wasm: *Wasm) !void {
2058 };2061 };
20592062
2060 const obj_file = wasm.file(@enumFromInt(file_index)).?;2063 const obj_file = wasm.file(@enumFromInt(file_index)).?;
2061 const symbol = obj_file.symbol[sym_loc.index];2064 const symbol = obj_file.symbol(sym_loc.index);
20622065
2063 if (symbol.isDead() or symbol.isUndefined()) {2066 if (symbol.isDead() or symbol.isUndefined()) {
2064 // Skip undefined symbols as they go in the `import` section2067 // Skip undefined symbols as they go in the `import` section
...@@ -2422,7 +2425,7 @@ pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32...@@ -2422,7 +2425,7 @@ pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32
2422 break :blk index;2425 break :blk index;
2423 },2426 },
2424 .section => {2427 .section => {
2425 const section_name = file.symbolName(symbol.index);2428 const section_name = obj_file.symbolName(symbol.index);
2426 if (mem.eql(u8, section_name, ".debug_info")) {2429 if (mem.eql(u8, section_name, ".debug_info")) {
2427 return wasm.debug_info_index orelse blk: {2430 return wasm.debug_info_index orelse blk: {
2428 wasm.debug_info_index = index;2431 wasm.debug_info_index = index;
...@@ -2705,8 +2708,8 @@ fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) lin...@@ -2705,8 +2708,8 @@ fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) lin
27052708
2706 try wasm.parseInputFiles(positionals.items);2709 try wasm.parseInputFiles(positionals.items);
27072710
2708 for (wasm.objects.items, 0..) |_, object_index| {2711 for (wasm.objects.items) |object_index| {
2709 try wasm.resolveSymbolsInObject(@as(u16, @intCast(object_index)));2712 try wasm.resolveSymbolsInObject(object_index);
2710 }2713 }
27112714
2712 var emit_features_count: u32 = 0;2715 var emit_features_count: u32 = 0;
...@@ -2788,8 +2791,8 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node)...@@ -2788,8 +2791,8 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node)
27882791
2789 try wasm.parseInputFiles(positionals.items);2792 try wasm.parseInputFiles(positionals.items);
27902793
2791 for (wasm.objects.items, 0..) |_, object_index| {2794 for (wasm.objects.items) |object_index| {
2792 try wasm.resolveSymbolsInObject(@as(u16, @intCast(object_index)));2795 try wasm.resolveSymbolsInObject(object_index);
2793 }2796 }
27942797
2795 var emit_features_count: u32 = 0;2798 var emit_features_count: u32 = 0;
src/link/Wasm/Atom.zig+13-9
...@@ -59,7 +59,10 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio...@@ -59,7 +59,10 @@ pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptio
5959
60/// Returns the location of the symbol that represents this `Atom`60/// Returns the location of the symbol that represents this `Atom`
61pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {61pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
62 return .{ .file = atom.file, .index = atom.sym_index };62 if (atom.file == .null) {
63 return .{ .file = null, .index = atom.sym_index };
64 }
65 return .{ .file = @intFromEnum(atom.file), .index = atom.sym_index };
63}66}
6467
65pub fn getSymbolIndex(atom: Atom) ?u32 {68pub fn getSymbolIndex(atom: Atom) ?u32 {
...@@ -80,7 +83,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {...@@ -80,7 +83,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
80 for (atom.relocs.items) |reloc| {83 for (atom.relocs.items) |reloc| {
81 const value = atom.relocationValue(reloc, wasm_bin);84 const value = atom.relocationValue(reloc, wasm_bin);
82 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{85 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{
83 (Wasm.SymbolLoc{ .file = atom.file, .index = reloc.index }).getName(wasm_bin),86 (Wasm.SymbolLoc{ .file = @intFromEnum(atom.file), .index = reloc.index }).getName(wasm_bin),
84 symbol_name,87 symbol_name,
85 reloc.offset,88 reloc.offset,
86 value,89 value,
...@@ -119,7 +122,11 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {...@@ -119,7 +122,11 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
119/// All values will be represented as a `u64` as all values can fit within it.122/// All values will be represented as a `u64` as all values can fit within it.
120/// The final value must be casted to the correct size.123/// The final value must be casted to the correct size.
121fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {124fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
122 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);125 const target_loc = if (atom.file == .null)
126 (Wasm.SymbolLoc{ .file = null, .index = relocation.index }).finalLoc(wasm_bin)
127 else
128 (Wasm.SymbolLoc{ .file = @intFromEnum(atom.file), .index = relocation.index }).finalLoc(wasm_bin);
129
123 const symbol = target_loc.getSymbol(wasm_bin);130 const symbol = target_loc.getSymbol(wasm_bin);
124 if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and131 if (relocation.relocation_type != .R_WASM_TYPE_INDEX_LEB and
125 symbol.tag != .section and132 symbol.tag != .section and
...@@ -135,13 +142,10 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa...@@ -135,13 +142,10 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
135 .R_WASM_TABLE_INDEX_I64,142 .R_WASM_TABLE_INDEX_I64,
136 .R_WASM_TABLE_INDEX_SLEB,143 .R_WASM_TABLE_INDEX_SLEB,
137 .R_WASM_TABLE_INDEX_SLEB64,144 .R_WASM_TABLE_INDEX_SLEB64,
138 => return wasm_bin.function_table.get(.{ .file = atom.file, .index = relocation.index }) orelse 0,145 => return wasm_bin.function_table.get(.{ .file = @intFromEnum(atom.file), .index = relocation.index }) orelse 0,
139 .R_WASM_TYPE_INDEX_LEB => {146 .R_WASM_TYPE_INDEX_LEB => {
140 const file_index = atom.file orelse {147 const obj_file = wasm_bin.file(atom.file) orelse return relocation.index;
141 return relocation.index;148 const original_type = obj_file.funcTypes()[relocation.index];
142 };
143
144 const original_type = wasm_bin.objects.items[file_index].func_types[relocation.index];
145 return wasm_bin.getTypeIndex(original_type).?;149 return wasm_bin.getTypeIndex(original_type).?;
146 },150 },
147 .R_WASM_GLOBAL_INDEX_I32,151 .R_WASM_GLOBAL_INDEX_I32,
src/link/Wasm/Object.zig+13-16
...@@ -135,7 +135,7 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz...@@ -135,7 +135,7 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz
135135
136 var is_object_file: bool = false;136 var is_object_file: bool = false;
137 const size = maybe_max_size orelse size: {137 const size = maybe_max_size orelse size: {
138 errdefer gpa.free(object.name);138 errdefer gpa.free(object.path);
139 const stat = try file.stat();139 const stat = try file.stat();
140 break :size @as(usize, @intCast(stat.size));140 break :size @as(usize, @intCast(stat.size));
141 };141 };
...@@ -202,18 +202,17 @@ pub fn deinit(object: *Object, gpa: Allocator) void {...@@ -202,18 +202,17 @@ pub fn deinit(object: *Object, gpa: Allocator) void {
202 }202 }
203 object.relocatable_data.deinit(gpa);203 object.relocatable_data.deinit(gpa);
204 object.string_table.deinit(gpa);204 object.string_table.deinit(gpa);
205 gpa.free(object.name);205 gpa.free(object.path);
206 object.* = undefined;206 object.* = undefined;
207}207}
208208
209/// Finds the import within the list of imports from a given kind and index of that kind.209/// Finds the import within the list of imports from a given kind and index of that kind.
210/// Asserts the import exists210/// Asserts the import exists
211pub fn findImport(object: *const Object, index: u32) types.Import {211pub fn findImport(object: *const Object, sym: Symbol) types.Import {
212 const sym = object.symtable[index];
213 var i: u32 = 0;212 var i: u32 = 0;
214 return for (object.imports) |import| {213 return for (object.imports) |import| {
215 if (std.meta.activeTag(import.kind) == sym.tag) {214 if (std.meta.activeTag(import.kind) == sym.tag.externalType()) {
216 if (i == index) return import;215 if (i == sym.index) return import;
217 i += 1;216 i += 1;
218 }217 }
219 } else unreachable; // Only existing imports are allowed to be found218 } else unreachable; // Only existing imports are allowed to be found
...@@ -231,14 +230,12 @@ fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {...@@ -231,14 +230,12 @@ fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {
231 if (sym.tag == .table) table_count += 1;230 if (sym.tag == .table) table_count += 1;
232 }231 }
233232
234 const import_table_count = object.importedCountByKind(.table);
235
236 // For each import table, we also have a symbol so this is not a legacy object file233 // For each import table, we also have a symbol so this is not a legacy object file
237 if (import_table_count == table_count) return null;234 if (object.imported_tables_count == table_count) return null;
238235
239 if (table_count != 0) {236 if (table_count != 0) {
240 log.err("Expected a table entry symbol for each of the {d} table(s), but instead got {d} symbols.", .{237 log.err("Expected a table entry symbol for each of the {d} table(s), but instead got {d} symbols.", .{
241 import_table_count,238 object.imported_tables_count,
242 table_count,239 table_count,
243 });240 });
244 return error.MissingTableSymbols;241 return error.MissingTableSymbols;
...@@ -250,7 +247,7 @@ fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {...@@ -250,7 +247,7 @@ fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {
250 return error.UnexpectedTable;247 return error.UnexpectedTable;
251 }248 }
252249
253 if (import_table_count != 1) {250 if (object.imported_tables_count != 1) {
254 log.err("Found more than one table import, but no representing table symbols", .{});251 log.err("Found more than one table import, but no representing table symbols", .{});
255 return error.MissingTableSymbols;252 return error.MissingTableSymbols;
256 }253 }
...@@ -519,7 +516,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -519,7 +516,7 @@ fn Parser(comptime ReaderType: type) type {
519 const start = reader.context.bytes_left;516 const start = reader.context.bytes_left;
520 var index: u32 = 0;517 var index: u32 = 0;
521 const count = try readLeb(u32, reader);518 const count = try readLeb(u32, reader);
522 const imported_function_count = parser.object.importedCountByKind(.function);519 const imported_function_count = parser.object.imported_functions_count;
523 var relocatable_data = try std.ArrayList(RelocatableData).initCapacity(gpa, count);520 var relocatable_data = try std.ArrayList(RelocatableData).initCapacity(gpa, count);
524 defer relocatable_data.deinit();521 defer relocatable_data.deinit();
525 while (index < count) : (index += 1) {522 while (index < count) : (index += 1) {
...@@ -836,7 +833,7 @@ fn Parser(comptime ReaderType: type) type {...@@ -836,7 +833,7 @@ fn Parser(comptime ReaderType: type) type {
836 defer gpa.free(name);833 defer gpa.free(name);
837 try reader.readNoEof(name);834 try reader.readNoEof(name);
838 break :name try parser.object.string_table.put(gpa, name);835 break :name try parser.object.string_table.put(gpa, name);
839 } else parser.object.findImport(symbol.tag.externalType(), symbol.index).name;836 } else parser.object.findImport(symbol).name;
840 },837 },
841 }838 }
842 return symbol;839 return symbol;
...@@ -915,7 +912,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato...@@ -915,7 +912,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
915 const gpa = comp.gpa;912 const gpa = comp.gpa;
916 const symbol = &object.symtable[symbol_index];913 const symbol = &object.symtable[symbol_index];
917 const relocatable_data: RelocatableData = switch (symbol.tag) {914 const relocatable_data: RelocatableData = switch (symbol.tag) {
918 .function => object.relocatable_data.get(.code).?[symbol.index - object.importedCountByKind(.function)],915 .function => object.relocatable_data.get(.code).?[symbol.index - object.imported_functions_count],
919 .data => object.relocatable_data.get(.data).?[symbol.index],916 .data => object.relocatable_data.get(.data).?[symbol.index],
920 .section => blk: {917 .section => blk: {
921 const data = object.relocatable_data.get(.custom).?;918 const data = object.relocatable_data.get(.custom).?;
...@@ -955,7 +952,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato...@@ -955,7 +952,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
955 .R_WASM_TABLE_INDEX_SLEB64,952 .R_WASM_TABLE_INDEX_SLEB64,
956 => {953 => {
957 try wasm.function_table.put(gpa, .{954 try wasm.function_table.put(gpa, .{
958 .file = object.index,955 .file = @intFromEnum(object.index),
959 .index = reloc.index,956 .index = reloc.index,
960 }, 0);957 }, 0);
961 },958 },
...@@ -966,7 +963,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato...@@ -966,7 +963,7 @@ pub fn parseSymbolIntoAtom(object: *Object, wasm: *Wasm, symbol_index: u32) !Ato
966 if (sym.tag != .global) {963 if (sym.tag != .global) {
967 try wasm.got_symbols.append(964 try wasm.got_symbols.append(
968 gpa,965 gpa,
969 .{ .file = object.index, .index = reloc.index },966 .{ .file = @intFromEnum(object.index), .index = reloc.index },
970 );967 );
971 }968 }
972 },969 },
src/link/Wasm/ZigObject.zig+8-7
...@@ -110,8 +110,9 @@ fn symbol(zig_object: *const ZigObject, index: u32) *Symbol {...@@ -110,8 +110,9 @@ fn symbol(zig_object: *const ZigObject, index: u32) *Symbol {
110110
111/// Frees and invalidates all memory of the incrementally compiled Zig module.111/// Frees and invalidates all memory of the incrementally compiled Zig module.
112/// It is illegal behavior to access the `ZigObject` after calling `deinit`.112/// It is illegal behavior to access the `ZigObject` after calling `deinit`.
113pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {113pub fn deinit(zig_object: *ZigObject, wasm_file: *Wasm) void {
114 for (zig_object.segment_info.values()) |segment_info| {114 const gpa = wasm_file.base.comp.gpa;
115 for (zig_object.segment_info.items) |segment_info| {
115 gpa.free(segment_info.name);116 gpa.free(segment_info.name);
116 }117 }
117118
...@@ -121,9 +122,9 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {...@@ -121,9 +122,9 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {
121 {122 {
122 var it = zig_object.decls.valueIterator();123 var it = zig_object.decls.valueIterator();
123 while (it.next()) |atom_index_ptr| {124 while (it.next()) |atom_index_ptr| {
124 const atom = zig_object.getAtomPtr(atom_index_ptr.*);125 const atom = wasm_file.getAtomPtr(atom_index_ptr.*);
125 for (atom.locals.items) |local_index| {126 for (atom.locals.items) |local_index| {
126 const local_atom = zig_object.getAtomPtr(local_index);127 const local_atom = wasm_file.getAtomPtr(local_index);
127 local_atom.deinit(gpa);128 local_atom.deinit(gpa);
128 }129 }
129 atom.deinit(gpa);130 atom.deinit(gpa);
...@@ -131,9 +132,9 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {...@@ -131,9 +132,9 @@ pub fn deinit(zig_object: *ZigObject, gpa: std.mem.Allocator) void {
131 }132 }
132 {133 {
133 for (zig_object.anon_decls.values()) |atom_index| {134 for (zig_object.anon_decls.values()) |atom_index| {
134 const atom = zig_object.getAtomPtr(atom_index);135 const atom = wasm_file.getAtomPtr(atom_index);
135 for (atom.locals.items) |local_index| {136 for (atom.locals.items) |local_index| {
136 const local_atom = zig_object.getAtomPtr(local_index);137 const local_atom = wasm_file.getAtomPtr(local_index);
137 local_atom.deinit(gpa);138 local_atom.deinit(gpa);
138 }139 }
139 atom.deinit(gpa);140 atom.deinit(gpa);
...@@ -1158,7 +1159,7 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:...@@ -1158,7 +1159,7 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:
1158/// The symbols in ZigObject are already represented by an atom as we need to store its data.1159/// The symbols in ZigObject are already represented by an atom as we need to store its data.
1159/// So rather than creating a new Atom and returning its index, we use this oppertunity to scan1160/// So rather than creating a new Atom and returning its index, we use this oppertunity to scan
1160/// its relocations and create any GOT symbols or function table indexes it may require.1161/// its relocations and create any GOT symbols or function table indexes it may require.
1161pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) Atom.Index {1162pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) !Atom.Index {
1162 const gpa = wasm_file.base.comp.gpa;1163 const gpa = wasm_file.base.comp.gpa;
1163 const loc: Wasm.SymbolLoc = .{ .file = @intFromEnum(zig_object.index), .index = index };1164 const loc: Wasm.SymbolLoc = .{ .file = @intFromEnum(zig_object.index), .index = index };
1164 const final_index = try wasm_file.getMatchingSegment(zig_object.index, index);1165 const final_index = try wasm_file.getMatchingSegment(zig_object.index, index);