authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-01-13 06:31:00+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-01-13 16:41:27+01:00
log5468684456b13b6465c4fcd50c072e5d5c8536a3
tree11bc75c13275bc6328c3a2efefff059ce73c0f3b
parentc77ca9174976a9fb8769276ce913e761d66af1de
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: implement the __heap_end symbol

When any of the object files reference the __heap_end symbol, we will create it as a synthetic symbol. The symbol only exists within the linker and will not be emit within the binary as it's solely used for relocations. The symbol represents where the heap ends, so allocators can determine whether to allocate a new page or not.

1 files changed, 30 insertions(+), 10 deletions(-)

src/link/Wasm.zig+30-10
......@@ -871,6 +871,22 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
871871 try wasm.parseAtom(atom, .{ .data = .synthetic });
872872 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom);
873873 }
874
875 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {
876 const loc = try wasm.createSyntheticSymbol("__heap_end", .data);
877 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
878 _ = wasm.resolved_symbols.swapRemove(loc);
879
880 const atom = try wasm.base.allocator.create(Atom);
881 errdefer wasm.base.allocator.destroy(atom);
882 try wasm.managed_atoms.append(wasm.base.allocator, atom);
883 atom.* = Atom.empty;
884 atom.sym_index = loc.index;
885 atom.alignment = 1;
886
887 try wasm.parseAtom(atom, .{ .data = .synthetic });
888 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom);
889 }
874890}
875891
876892// Tries to find a global symbol by its name. Returns null when not found,
......@@ -892,14 +908,8 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void {
892908 const file_name = if (undef.file) |file_index| name: {
893909 break :name wasm.objects.items[file_index].name;
894910 } else wasm.name;
895 const import_name = if (undef.file) |file_index| name: {
896 const obj = wasm.objects.items[file_index];
897 const name_index = if (symbol.tag == .function) name_index: {
898 break :name_index obj.findImport(symbol.tag.externalType(), symbol.index).name;
899 } else symbol.name;
900 break :name obj.string_table.get(name_index);
901 } else wasm.string_table.get(wasm.imports.get(undef).?.name);
902 log.err("could not resolve undefined symbol '{s}'", .{import_name});
911 const symbol_name = undef.getName(wasm);
912 log.err("could not resolve undefined symbol '{s}'", .{symbol_name});
903913 log.err(" defined in '{s}'", .{file_name});
904914 }
905915 }
......@@ -2223,12 +2233,20 @@ fn setupMemory(wasm: *Wasm) !void {
22232233 }
22242234 memory_ptr = initial_memory;
22252235 }
2226
2236 memory_ptr = mem.alignForwardGeneric(u64, memory_ptr, std.wasm.page_size);
22272237 // In case we do not import memory, but define it ourselves,
22282238 // set the minimum amount of pages on the memory section.
2229 wasm.memories.limits.min = @intCast(u32, std.mem.alignForwardGeneric(u64, memory_ptr, page_size) / page_size);
2239 wasm.memories.limits.min = @intCast(u32, memory_ptr / page_size);
22302240 log.debug("Total memory pages: {d}", .{wasm.memories.limits.min});
22312241
2242 if (wasm.findGlobalSymbol("__heap_end")) |loc| {
2243 const segment_index = wasm.data_segments.get(".synthetic").?;
2244 const segment = &wasm.segments.items[segment_index];
2245 segment.offset = 0;
2246 const atom = wasm.symbol_atom.get(loc).?;
2247 atom.offset = @intCast(u32, memory_ptr);
2248 }
2249
22322250 if (wasm.base.options.max_memory) |max_memory| {
22332251 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {
22342252 log.err("Maximum memory must be {d}-byte aligned", .{page_size});
......@@ -3392,6 +3410,8 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
33923410 // bss section is not emitted when this condition holds true, so we also
33933411 // do not output a name for it.
33943412 if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue;
3413 // Synthetic segments are not emitted
3414 if (std.mem.eql(u8, key, ".synthetic")) continue;
33953415 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });
33963416 data_segment_index += 1;
33973417 }