authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-02 21:41:47+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-05-09 18:51:46+02:00
log9b6b7034c20a0089b88e58b5142c91b2d26bcef8
tree83d346c2e35e381bf019430205b0937f072177bd
parentf76027220042d965278184088f1f04b6c8430bcb

wasm: Flush debug information + commit decl

This implements parts to commit a decl's debug information into a linear memory buffer. The goal is to write this buffer at once after we finished linking.

2 files changed, 77 insertions(+), 1 deletions(-)

src/link/Dwarf.zig+28-1
......@@ -818,6 +818,7 @@ pub fn commitDeclState(
818818 const src_fn = switch (self.tag) {
819819 .elf => &decl.fn_link.elf,
820820 .macho => &decl.fn_link.macho,
821 .wasm => &decl.fn_link.wasm.src_fn,
821822 else => unreachable, // TODO
822823 };
823824 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
......@@ -958,6 +959,26 @@ pub fn commitDeclState(
958959 next_padding_size,
959960 );
960961 },
962 .wasm => {
963 const wasm_file = file.cast(File.Wasm).?;
964 const segment_index = try wasm_file.getDebugLineIndex();
965 const segment = &wasm_file.segments.items[segment_index];
966 const debug_atom = wasm_file.atoms.get(segment_index).?;
967 if (needed_size != segment.size) {
968 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
969 if (needed_size > segment.size) {
970 log.debug(" allocating {d} bytes for debug line information", .{needed_size - segment.size});
971 try debug_atom.code.resize(self.allocator, needed_size);
972 std.mem.set(u8, debug_atom.code.items[segment.size..], 0);
973 }
974 debug_atom.size = needed_size;
975 segment.size = needed_size;
976 }
977 // since we can tighly pack the debug lines, wasm does not require
978 // us to pad with Nops.
979 const offset = segment.offset + src_fn.off;
980 std.mem.copy(u8, debug_atom.code.items[offset..], dbg_line_buffer.items);
981 },
961982 else => unreachable,
962983 }
963984
......@@ -973,6 +994,7 @@ pub fn commitDeclState(
973994 const atom = switch (self.tag) {
974995 .elf => &decl.link.elf.dbg_info_atom,
975996 .macho => &decl.link.macho.dbg_info_atom,
997 .wasm => &decl.link.wasm.dbg_info_atom,
976998 else => unreachable,
977999 };
9781000
......@@ -1094,6 +1116,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
10941116 const file_pos = debug_info_sect.offset + atom.off;
10951117 try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
10961118 },
1119 .wasm => {},
10971120 else => unreachable,
10981121 }
10991122 // TODO Look at the free list before appending at the end.
......@@ -1253,7 +1276,11 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
12531276 },
12541277 .wasm => {
12551278 const wasm_file = file.cast(File.Wasm).?;
1256 _ = wasm_file; // TODO, update .debug_line
1279 const segment_index = wasm_file.getDebugLineIndex() catch unreachable;
1280 const segment = wasm_file.segments.items[segment_index];
1281 const offset = segment.offset + decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
1282 const debug_atom = wasm_file.atoms.get(segment_index).?;
1283 std.mem.copy(u8, debug_atom.code.items[offset..], &data);
12571284 },
12581285 else => unreachable,
12591286 }
src/link/Wasm.zig+49
......@@ -62,6 +62,10 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
6262/// Represents the index into `segments` where the 'code' section
6363/// lives.
6464code_section_index: ?u32 = null,
65/// The index of the segment representing the custom '.debug_info' section.
66debug_info_index: ?u32 = null,
67/// The index of the segment representing the custom '.debug_line' section.
68debug_line_index: ?u32 = null,
6569/// The count of imported functions. This number will be appended
6670/// to the function indexes as their index starts at the lowest non-extern function.
6771imported_functions_count: u32 = 0,
......@@ -311,6 +315,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
311315 .init = .{ .i32_const = 0 },
312316 };
313317 }
318
314319 return wasm_bin;
315320}
316321
......@@ -566,6 +571,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
566571 },
567572 };
568573
574 if (self.dwarf) |*dwarf| {
575 try dwarf.commitDeclState(
576 &self.base,
577 mod,
578 decl,
579 // Actual value will be written after relocation
580 0,
581 code.len,
582 &decl_state.?,
583 );
584 }
569585 return self.finishUpdateDecl(decl, code);
570586}
571587
......@@ -1517,6 +1533,35 @@ fn populateErrorNameTable(self: *Wasm) !void {
15171533 try self.parseAtom(names_atom, .data);
15181534}
15191535
1536pub fn getDebugInfoIndex(self: *Wasm) !u32 {
1537 assert(self.dwarf != null);
1538 return self.debug_info_index orelse {
1539 self.debug_info_index = @intCast(u32, self.segments.items.len);
1540 const segment = try self.segments.addOne(self.base.allocator);
1541 segment.* = .{
1542 .size = 0,
1543 .offset = 0,
1544 // debug sections always have alignment '1'
1545 .alignment = 1,
1546 };
1547 return self.debug_info_index.?;
1548 };
1549}
1550
1551pub fn getDebugLineIndex(self: *Wasm) !u32 {
1552 assert(self.dwarf != null);
1553 return self.debug_line_index orelse {
1554 self.debug_line_index = @intCast(u32, self.segments.items.len);
1555 const segment = try self.segments.addOne(self.base.allocator);
1556 segment.* = .{
1557 .size = 0,
1558 .offset = 0,
1559 .alignment = 1,
1560 };
1561 return self.debug_line_index.?;
1562 };
1563}
1564
15201565fn resetState(self: *Wasm) void {
15211566 for (self.segment_info.items) |*segment_info| {
15221567 self.base.allocator.free(segment_info.name);
......@@ -1542,6 +1587,7 @@ fn resetState(self: *Wasm) void {
15421587 self.atoms.clearRetainingCapacity();
15431588 self.symbol_atom.clearRetainingCapacity();
15441589 self.code_section_index = null;
1590 self.debug_info_index = null;
15451591}
15461592
15471593pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
......@@ -1636,6 +1682,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
16361682 try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self);
16371683 }
16381684
1685 if (self.dwarf) |*dwarf| {
1686 try dwarf.flushModule(&self.base, self.base.options.module.?);
1687 }
16391688 try self.allocateAtoms();
16401689 try self.setupMemory();
16411690 self.mapFunctionTable();