authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-06-11 03:10:54-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-11 03:01:31-07:00
log7507a76879bbfb53c170f130ea836b10bc2a42e1
treed7e637560ce3ecbf8e5795c9ebd1e4d64352e428
parent7e5dea6366fa194b54cc391ba48c18754df198e7

link: use `Wasm.string_table` offsets for `Wasm.undefs` keys

This avoids having dangling pointers into `InternPool.string_bytes`.

1 files changed, 37 insertions(+), 23 deletions(-)

src/link/Wasm.zig+37-23
...@@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{},...@@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{},
149/// into the final binary.149/// into the final binary.
150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},
151/// Symbols that remain undefined after symbol resolution.151/// Symbols that remain undefined after symbol resolution.
152undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{},152/// Note: The key represents an offset into the string table, rather than the actual string.
153undefs: std.AutoArrayHashMapUnmanaged(u32, SymbolLoc) = .{},
153/// Maps a symbol's location to an atom. This can be used to find meta154/// Maps a symbol's location to an atom. This can be used to find meta
154/// data of a symbol, such as its size, or its offset to perform a relocation.155/// data of a symbol, such as its size, or its offset to perform a relocation.
155/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.156/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.
...@@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {...@@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
514/// Leaves index undefined and the default flags (0).515/// Leaves index undefined and the default flags (0).
515fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {516fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {
516 const name_offset = try wasm.string_table.put(wasm.base.allocator, name);517 const name_offset = try wasm.string_table.put(wasm.base.allocator, name);
518 return wasm.createSyntheticSymbolOffset(name_offset, tag);
519}
520
521fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc {
517 const sym_index = @intCast(u32, wasm.symbols.items.len);522 const sym_index = @intCast(u32, wasm.symbols.items.len);
518 const loc: SymbolLoc = .{ .index = sym_index, .file = null };523 const loc: SymbolLoc = .{ .index = sym_index, .file = null };
519 try wasm.symbols.append(wasm.base.allocator, .{524 try wasm.symbols.append(wasm.base.allocator, .{
...@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
691 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});696 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
692697
693 if (symbol.isUndefined()) {698 if (symbol.isUndefined()) {
694 try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name, location);699 try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name_index, location);
695 }700 }
696 continue;701 continue;
697 }702 }
...@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {...@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
801 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});806 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
802 assert(wasm.resolved_symbols.swapRemove(existing_loc));807 assert(wasm.resolved_symbols.swapRemove(existing_loc));
803 if (existing_sym.isUndefined()) {808 if (existing_sym.isUndefined()) {
804 _ = wasm.undefs.swapRemove(sym_name);809 _ = wasm.undefs.swapRemove(sym_name_index);
805 }810 }
806 }811 }
807}812}
...@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {...@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
812 log.debug("Resolving symbols in archives", .{});817 log.debug("Resolving symbols in archives", .{});
813 var index: u32 = 0;818 var index: u32 = 0;
814 undef_loop: while (index < wasm.undefs.count()) {819 undef_loop: while (index < wasm.undefs.count()) {
815 const sym_name = wasm.undefs.keys()[index];820 const sym_name_index = wasm.undefs.keys()[index];
816821
817 for (wasm.archives.items) |archive| {822 for (wasm.archives.items) |archive| {
823 const sym_name = wasm.string_table.get(sym_name_index);
824 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
818 const offset = archive.toc.get(sym_name) orelse {825 const offset = archive.toc.get(sym_name) orelse {
819 // symbol does not exist in this archive826 // symbol does not exist in this archive
820 continue;827 continue;
821 };828 };
822829
823 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
824 // Symbol is found in unparsed object file within current archive.830 // Symbol is found in unparsed object file within current archive.
825 // Parse object and and resolve symbols again before we check remaining831 // Parse object and and resolve symbols again before we check remaining
826 // undefined symbols.832 // undefined symbols.
...@@ -1191,28 +1197,36 @@ fn validateFeatures(...@@ -1191,28 +1197,36 @@ fn validateFeatures(
1191/// if one or multiple undefined references exist. When none exist, the symbol will1197/// if one or multiple undefined references exist. When none exist, the symbol will
1192/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.1198/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
1193fn resolveLazySymbols(wasm: *Wasm) !void {1199fn resolveLazySymbols(wasm: *Wasm) !void {
1194 if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| {1200 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
1195 const loc = try wasm.createSyntheticSymbol("__heap_base", .data);1201 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1196 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1202 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1197 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.1203 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1204 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.
1205 }
1198 }1206 }
11991207
1200 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {1208 if (wasm.string_table.getOffset("__heap_end")) |name_offset| {
1201 const loc = try wasm.createSyntheticSymbol("__heap_end", .data);1209 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1202 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1210 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1203 _ = wasm.resolved_symbols.swapRemove(loc);1211 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1212 _ = wasm.resolved_symbols.swapRemove(loc);
1213 }
1204 }1214 }
12051215
1206 if (!wasm.base.options.shared_memory) {1216 if (!wasm.base.options.shared_memory) {
1207 if (wasm.undefs.fetchSwapRemove("__tls_base")) |kv| {1217 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
1208 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);1218 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1209 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1219 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
1220 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1221 }
1210 }1222 }
1211 }1223 }
1212 if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| {1224 if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| {
1213 const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data);1225 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1214 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);1226 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1215 _ = wasm.resolved_symbols.swapRemove(kv.value);1227 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1228 _ = wasm.resolved_symbols.swapRemove(kv.value);
1229 }
1216 }1230 }
1217}1231}
12181232
...@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3...@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3
1611 wasm.symbols.items[sym_index] = symbol;1625 wasm.symbols.items[sym_index] = symbol;
1612 gop.value_ptr.* = .{ .index = sym_index, .file = null };1626 gop.value_ptr.* = .{ .index = sym_index, .file = null };
1613 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});1627 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});
1614 try wasm.undefs.putNoClobber(wasm.base.allocator, name, gop.value_ptr.*);1628 try wasm.undefs.putNoClobber(wasm.base.allocator, name_index, gop.value_ptr.*);
1615 return sym_index;1629 return sym_index;
1616}1630}
16171631
...@@ -1769,7 +1783,7 @@ pub fn updateDeclExports(...@@ -1769,7 +1783,7 @@ pub fn updateDeclExports(
17691783
1770 // if the symbol was previously undefined, remove it as an import1784 // if the symbol was previously undefined, remove it as an import
1771 _ = wasm.imports.remove(sym_loc);1785 _ = wasm.imports.remove(sym_loc);
1772 _ = wasm.undefs.swapRemove(mod.intern_pool.stringToSlice(exp.name));1786 _ = wasm.undefs.swapRemove(export_name);
1773 }1787 }
1774}1788}
17751789
...@@ -1885,7 +1899,7 @@ pub fn addOrUpdateImport(...@@ -1885,7 +1899,7 @@ pub fn addOrUpdateImport(
1885 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };1899 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
1886 global_gop.value_ptr.* = loc;1900 global_gop.value_ptr.* = loc;
1887 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});1901 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1888 try wasm.undefs.putNoClobber(wasm.base.allocator, full_name, loc);1902 try wasm.undefs.putNoClobber(wasm.base.allocator, decl_name_index, loc);
1889 }1903 }
18901904
1891 if (type_index) |ty_index| {1905 if (type_index) |ty_index| {