authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-13 22:14:48+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-04-14 22:53:13+02:00
logd66c61a2cf69665223815a1a12a1f93b30b99571
tree2f969fb2733eadc8ae16088ce98b0b19a5841ce8
parentcf37101108e56412e958a8b597bae84649893b6f

wasm-linker: Prevent overalignment for segments

Previously, the data segments were being aligned twice. This caused us to overalign the segment and therefore allocate a much larger size for each segment than was required. This fix ensures we align and set the size just once, ensuring semantically correct binaries as well as smaller binaries.

2 files changed, 7 insertions(+), 15 deletions(-)

src/link/Wasm.zig+7-10
......@@ -962,11 +962,6 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
962962
963963 const segment: *Segment = &self.segments.items[final_index];
964964 segment.alignment = std.math.max(segment.alignment, atom.alignment);
965 segment.size = std.mem.alignForwardGeneric(
966 u32,
967 std.mem.alignForwardGeneric(u32, segment.size, atom.alignment) + atom.size,
968 segment.alignment,
969 );
970965
971966 if (self.atoms.getPtr(final_index)) |last| {
972967 last.*.next = atom;
......@@ -978,9 +973,10 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
978973}
979974
980975fn allocateAtoms(self: *Wasm) !void {
981 var it = self.atoms.valueIterator();
982 while (it.next()) |current_atom| {
983 var atom: *Atom = current_atom.*.getFirst();
976 var it = self.atoms.iterator();
977 while (it.next()) |entry| {
978 const segment = &self.segments.items[entry.key_ptr.*];
979 var atom: *Atom = entry.value_ptr.*.getFirst();
984980 var offset: u32 = 0;
985981 while (true) {
986982 offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment);
......@@ -996,6 +992,7 @@ fn allocateAtoms(self: *Wasm) !void {
996992 self.symbol_atom.putAssumeCapacity(atom.symbolLoc(), atom); // Update atom pointers
997993 atom = atom.next orelse break;
998994 }
995 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);
999996 }
1000997}
1001998
......@@ -1566,8 +1563,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
15661563 try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self);
15671564 }
15681565
1569 try self.setupMemory();
15701566 try self.allocateAtoms();
1567 try self.setupMemory();
15711568 self.mapFunctionTable();
15721569 try self.mergeSections();
15731570 try self.mergeTypes();
......@@ -1832,7 +1829,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void {
18321829 segment_count += 1;
18331830 const atom_index = entry.value_ptr.*;
18341831 var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst();
1835 var segment = self.segments.items[atom_index];
1832 const segment = self.segments.items[atom_index];
18361833
18371834 // flag and index to memory section (currently, there can only be 1 memory section in wasm)
18381835 try leb.writeULEB128(writer, @as(u32, 0));
src/link/Wasm/Object.zig-5
......@@ -865,11 +865,6 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
865865
866866 const segment: *Wasm.Segment = &wasm_bin.segments.items[final_index];
867867 segment.alignment = std.math.max(segment.alignment, atom.alignment);
868 segment.size = std.mem.alignForwardGeneric(
869 u32,
870 std.mem.alignForwardGeneric(u32, segment.size, atom.alignment) + atom.size,
871 segment.alignment,
872 );
873868
874869 if (wasm_bin.atoms.getPtr(final_index)) |last| {
875870 last.*.next = atom;