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) = .{},
149149/// into the final binary.
150150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},
151151/// 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) = .{},
153154/// Maps a symbol's location to an atom. This can be used to find meta
154155/// data of a symbol, such as its size, or its offset to perform a relocation.
155156/// 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 {
514515/// Leaves index undefined and the default flags (0).
515516fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {
516517 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 {
517522 const sym_index = @intCast(u32, wasm.symbols.items.len);
518523 const loc: SymbolLoc = .{ .index = sym_index, .file = null };
519524 try wasm.symbols.append(wasm.base.allocator, .{
......@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
691696 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
692697
693698 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);
695700 }
696701 continue;
697702 }
......@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
801806 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
802807 assert(wasm.resolved_symbols.swapRemove(existing_loc));
803808 if (existing_sym.isUndefined()) {
804 _ = wasm.undefs.swapRemove(sym_name);
809 _ = wasm.undefs.swapRemove(sym_name_index);
805810 }
806811 }
807812}
......@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
812817 log.debug("Resolving symbols in archives", .{});
813818 var index: u32 = 0;
814819 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
817822 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 });
818825 const offset = archive.toc.get(sym_name) orelse {
819826 // symbol does not exist in this archive
820827 continue;
821828 };
822829
823 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
824830 // Symbol is found in unparsed object file within current archive.
825831 // Parse object and and resolve symbols again before we check remaining
826832 // undefined symbols.
......@@ -1191,28 +1197,36 @@ fn validateFeatures(
11911197/// if one or multiple undefined references exist. When none exist, the symbol will
11921198/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
11931199fn resolveLazySymbols(wasm: *Wasm) !void {
1194 if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| {
1195 const loc = try wasm.createSyntheticSymbol("__heap_base", .data);
1196 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1197 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.
1200 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
1201 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1202 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
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 }
11981206 }
11991207
1200 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {
1201 const loc = try wasm.createSyntheticSymbol("__heap_end", .data);
1202 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1203 _ = wasm.resolved_symbols.swapRemove(loc);
1208 if (wasm.string_table.getOffset("__heap_end")) |name_offset| {
1209 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1210 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1211 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1212 _ = wasm.resolved_symbols.swapRemove(loc);
1213 }
12041214 }
12051215
12061216 if (!wasm.base.options.shared_memory) {
1207 if (wasm.undefs.fetchSwapRemove("__tls_base")) |kv| {
1208 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);
1209 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1217 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
1218 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1219 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
1220 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1221 }
12101222 }
12111223 }
1212 if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| {
1213 const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data);
1214 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1215 _ = wasm.resolved_symbols.swapRemove(kv.value);
1224 if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| {
1225 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1226 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1227 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1228 _ = wasm.resolved_symbols.swapRemove(kv.value);
1229 }
12161230 }
12171231}
12181232
......@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3
16111625 wasm.symbols.items[sym_index] = symbol;
16121626 gop.value_ptr.* = .{ .index = sym_index, .file = null };
16131627 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.*);
16151629 return sym_index;
16161630}
16171631
......@@ -1769,7 +1783,7 @@ pub fn updateDeclExports(
17691783
17701784 // if the symbol was previously undefined, remove it as an import
17711785 _ = wasm.imports.remove(sym_loc);
1772 _ = wasm.undefs.swapRemove(mod.intern_pool.stringToSlice(exp.name));
1786 _ = wasm.undefs.swapRemove(export_name);
17731787 }
17741788}
17751789
......@@ -1885,7 +1899,7 @@ pub fn addOrUpdateImport(
18851899 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
18861900 global_gop.value_ptr.* = loc;
18871901 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);
18891903 }
18901904
18911905 if (type_index) |ty_index| {