| author | |
| committer | |
| log | 9b6b7034c20a0089b88e58b5142c91b2d26bcef8 |
| tree | 83d346c2e35e381bf019430205b0937f072177bd |
| parent | f76027220042d965278184088f1f04b6c8430bcb |
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( |
| 818 | 818 | const src_fn = switch (self.tag) { |
| 819 | 819 | .elf => &decl.fn_link.elf, |
| 820 | 820 | .macho => &decl.fn_link.macho, |
| 821 | .wasm => &decl.fn_link.wasm.src_fn, | |
| 821 | 822 | else => unreachable, // TODO |
| 822 | 823 | }; |
| 823 | 824 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| ... | ... | @@ -958,6 +959,26 @@ pub fn commitDeclState( |
| 958 | 959 | next_padding_size, |
| 959 | 960 | ); |
| 960 | 961 | }, |
| 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 | }, | |
| 961 | 982 | else => unreachable, |
| 962 | 983 | } |
| 963 | 984 | |
| ... | ... | @@ -973,6 +994,7 @@ pub fn commitDeclState( |
| 973 | 994 | const atom = switch (self.tag) { |
| 974 | 995 | .elf => &decl.link.elf.dbg_info_atom, |
| 975 | 996 | .macho => &decl.link.macho.dbg_info_atom, |
| 997 | .wasm => &decl.link.wasm.dbg_info_atom, | |
| 976 | 998 | else => unreachable, |
| 977 | 999 | }; |
| 978 | 1000 | |
| ... | ... | @@ -1094,6 +1116,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3 |
| 1094 | 1116 | const file_pos = debug_info_sect.offset + atom.off; |
| 1095 | 1117 | try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false); |
| 1096 | 1118 | }, |
| 1119 | .wasm => {}, | |
| 1097 | 1120 | else => unreachable, |
| 1098 | 1121 | } |
| 1099 | 1122 | // 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) |
| 1253 | 1276 | }, |
| 1254 | 1277 | .wasm => { |
| 1255 | 1278 | 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); | |
| 1257 | 1284 | }, |
| 1258 | 1285 | else => unreachable, |
| 1259 | 1286 | } |
src/link/Wasm.zig+49| ... | ... | @@ -62,6 +62,10 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 62 | 62 | /// Represents the index into `segments` where the 'code' section |
| 63 | 63 | /// lives. |
| 64 | 64 | code_section_index: ?u32 = null, |
| 65 | /// The index of the segment representing the custom '.debug_info' section. | |
| 66 | debug_info_index: ?u32 = null, | |
| 67 | /// The index of the segment representing the custom '.debug_line' section. | |
| 68 | debug_line_index: ?u32 = null, | |
| 65 | 69 | /// The count of imported functions. This number will be appended |
| 66 | 70 | /// to the function indexes as their index starts at the lowest non-extern function. |
| 67 | 71 | imported_functions_count: u32 = 0, |
| ... | ... | @@ -311,6 +315,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 311 | 315 | .init = .{ .i32_const = 0 }, |
| 312 | 316 | }; |
| 313 | 317 | } |
| 318 | ||
| 314 | 319 | return wasm_bin; |
| 315 | 320 | } |
| 316 | 321 | |
| ... | ... | @@ -566,6 +571,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes |
| 566 | 571 | }, |
| 567 | 572 | }; |
| 568 | 573 | |
| 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 | } | |
| 569 | 585 | return self.finishUpdateDecl(decl, code); |
| 570 | 586 | } |
| 571 | 587 | |
| ... | ... | @@ -1517,6 +1533,35 @@ fn populateErrorNameTable(self: *Wasm) !void { |
| 1517 | 1533 | try self.parseAtom(names_atom, .data); |
| 1518 | 1534 | } |
| 1519 | 1535 | |
| 1536 | pub 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 | ||
| 1551 | pub 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 | ||
| 1520 | 1565 | fn resetState(self: *Wasm) void { |
| 1521 | 1566 | for (self.segment_info.items) |*segment_info| { |
| 1522 | 1567 | self.base.allocator.free(segment_info.name); |
| ... | ... | @@ -1542,6 +1587,7 @@ fn resetState(self: *Wasm) void { |
| 1542 | 1587 | self.atoms.clearRetainingCapacity(); |
| 1543 | 1588 | self.symbol_atom.clearRetainingCapacity(); |
| 1544 | 1589 | self.code_section_index = null; |
| 1590 | self.debug_info_index = null; | |
| 1545 | 1591 | } |
| 1546 | 1592 | |
| 1547 | 1593 | 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 |
| 1636 | 1682 | try self.objects.items[object_index].parseIntoAtoms(self.base.allocator, object_index, self); |
| 1637 | 1683 | } |
| 1638 | 1684 | |
| 1685 | if (self.dwarf) |*dwarf| { | |
| 1686 | try dwarf.flushModule(&self.base, self.base.options.module.?); | |
| 1687 | } | |
| 1639 | 1688 | try self.allocateAtoms(); |
| 1640 | 1689 | try self.setupMemory(); |
| 1641 | 1690 | self.mapFunctionTable(); |