Commit 9b6b7034c2
src/link/Dwarf.zig
@@ -818,6 +818,7 @@ pub fn commitDeclState(
const src_fn = switch (self.tag) {
.elf => &decl.fn_link.elf,
.macho => &decl.fn_link.macho,
+ .wasm => &decl.fn_link.wasm.src_fn,
else => unreachable, // TODO
};
src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
@@ -958,6 +959,26 @@ pub fn commitDeclState(
next_padding_size,
);
},
+ .wasm => {
+ const wasm_file = file.cast(File.Wasm).?;
+ const segment_index = try wasm_file.getDebugLineIndex();
+ const segment = &wasm_file.segments.items[segment_index];
+ const debug_atom = wasm_file.atoms.get(segment_index).?;
+ if (needed_size != segment.size) {
+ log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
+ if (needed_size > segment.size) {
+ log.debug(" allocating {d} bytes for debug line information", .{needed_size - segment.size});
+ try debug_atom.code.resize(self.allocator, needed_size);
+ std.mem.set(u8, debug_atom.code.items[segment.size..], 0);
+ }
+ debug_atom.size = needed_size;
+ segment.size = needed_size;
+ }
+ // since we can tighly pack the debug lines, wasm does not require
+ // us to pad with Nops.
+ const offset = segment.offset + src_fn.off;
+ std.mem.copy(u8, debug_atom.code.items[offset..], dbg_line_buffer.items);
+ },
else => unreachable,
}
@@ -973,6 +994,7 @@ pub fn commitDeclState(
const atom = switch (self.tag) {
.elf => &decl.link.elf.dbg_info_atom,
.macho => &decl.link.macho.dbg_info_atom,
+ .wasm => &decl.link.wasm.dbg_info_atom,
else => unreachable,
};
@@ -1094,6 +1116,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
const file_pos = debug_info_sect.offset + atom.off;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
},
+ .wasm => {},
else => unreachable,
}
// 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)
},
.wasm => {
const wasm_file = file.cast(File.Wasm).?;
- _ = wasm_file; // TODO, update .debug_line
+ const segment_index = wasm_file.getDebugLineIndex() catch unreachable;
+ const segment = wasm_file.segments.items[segment_index];
+ const offset = segment.offset + decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
+ const debug_atom = wasm_file.atoms.get(segment_index).?;
+ std.mem.copy(u8, debug_atom.code.items[offset..], &data);
},
else => unreachable,
}
src/link/Wasm.zig
@@ -62,6 +62,10 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
/// Represents the index into `segments` where the 'code' section
/// lives.
code_section_index: ?u32 = null,
+/// The index of the segment representing the custom '.debug_info' section.
+debug_info_index: ?u32 = null,
+/// The index of the segment representing the custom '.debug_line' section.
+debug_line_index: ?u32 = null,
/// The count of imported functions. This number will be appended
/// to the function indexes as their index starts at the lowest non-extern function.
imported_functions_count: u32 = 0,
@@ -311,6 +315,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
.init = .{ .i32_const = 0 },
};
}
+
return wasm_bin;
}
@@ -566,6 +571,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
},
};
+ if (self.dwarf) |*dwarf| {
+ try dwarf.commitDeclState(
+ &self.base,
+ mod,
+ decl,
+ // Actual value will be written after relocation
+ 0,
+ code.len,
+ &decl_state.?,
+ );
+ }
return self.finishUpdateDecl(decl, code);
}
@@ -1517,6 +1533,35 @@ fn populateErrorNameTable(self: *Wasm) !void {
try self.parseAtom(names_atom, .data);
}
+pub fn getDebugInfoIndex(self: *Wasm) !u32 {
+ assert(self.dwarf != null);
+ return self.debug_info_index orelse {
+ self.debug_info_index = @intCast(u32, self.segments.items.len);
+ const segment = try self.segments.addOne(self.base.allocator);
+ segment.* = .{
+ .size = 0,
+ .offset = 0,
+ // debug sections always have alignment '1'
+ .alignment = 1,
+ };
+ return self.debug_info_index.?;
+ };
+}
+
+pub fn getDebugLineIndex(self: *Wasm) !u32 {
+ assert(self.dwarf != null);
+ return self.debug_line_index orelse {
+ self.debug_line_index = @intCast(u32, self.segments.items.len);
+ const segment = try self.segments.addOne(self.base.allocator);
+ segment.* = .{
+ .size = 0,
+ .offset = 0,
+ .alignment = 1,
+ };
+ return self.debug_line_index.?;
+ };
+}
+
fn resetState(self: *Wasm) void {
for (self.segment_info.items) |*segment_info| {
self.base.allocator.free(segment_info.name);
@@ -1542,6 +1587,7 @@ fn resetState(self: *Wasm) void {
self.atoms.clearRetainingCapacity();
self.symbol_atom.clearRetainingCapacity();
self.code_section_index = null;
+ self.debug_info_index = null;
}
pub 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
try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self);
}
+ if (self.dwarf) |*dwarf| {
+ try dwarf.flushModule(&self.base, self.base.options.module.?);
+ }
try self.allocateAtoms();
try self.setupMemory();
self.mapFunctionTable();