authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-09-02 21:13:59+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-09-07 18:53:16+02:00
logb2718e213ed7e7cd8bcd85bdf49d7ae33c857c58
tree20879860762e6645ed26f747221b821a0b1e6405
parent46c932a2c9650f14ae8035d7382d825bfabdc0a5
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: use Atoms for zig debug info

Previously we used single arraylists for each debug section for debug information that was generated from Zig code. (e.i. `Module` is available). This information is now stored in Atoms, similarly to debug information from object files. This will allow us to link them together and resolve debug relocations.

2 files changed, 45 insertions(+), 57 deletions(-)

src/link/Dwarf.zig+29-16
......@@ -861,7 +861,9 @@ pub fn commitDeclState(
861861 },
862862 .wasm => {
863863 const wasm_file = file.cast(File.Wasm).?;
864 writeDbgLineNopsBuffered(wasm_file.debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
864 const segment_index = wasm_file.debug_line_index.?;
865 const debug_line = wasm_file.atoms.get(segment_index).?.code;
866 writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
865867 },
866868 else => unreachable,
867869 }
......@@ -972,9 +974,9 @@ pub fn commitDeclState(
972974 },
973975 .wasm => {
974976 const wasm_file = file.cast(File.Wasm).?;
975 const segment_index = try wasm_file.getDebugLineIndex();
977 const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_line_index);
976978 const segment = &wasm_file.segments.items[segment_index];
977 const debug_line = &wasm_file.debug_line;
979 const debug_line = &wasm_file.atoms.get(segment_index).?.code;
978980 if (needed_size != segment.size) {
979981 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
980982 if (needed_size > segment.size) {
......@@ -1146,10 +1148,11 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
11461148 },
11471149 .wasm => {
11481150 const wasm_file = file.cast(File.Wasm).?;
1149 const segment_index = try wasm_file.getDebugInfoIndex();
1151 const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_info_index);
11501152 const segment = &wasm_file.segments.items[segment_index];
1153 const debug_info = &wasm_file.atoms.get(segment_index).?.code;
11511154 const offset = segment.offset + atom.off;
1152 try writeDbgInfoNopsToArrayList(gpa, &wasm_file.debug_info, offset, 0, &.{0}, atom.len, false);
1155 try writeDbgInfoNopsToArrayList(gpa, debug_info, offset, 0, &.{0}, atom.len, false);
11531156 },
11541157 else => unreachable,
11551158 }
......@@ -1276,9 +1279,9 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
12761279 },
12771280 .wasm => {
12781281 const wasm_file = file.cast(File.Wasm).?;
1279 const segment_index = try wasm_file.getDebugInfoIndex();
1282 const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_info_index);
12801283 const segment = &wasm_file.segments.items[segment_index];
1281 const debug_info = &wasm_file.debug_info;
1284 const debug_info = &wasm_file.atoms.get(segment_index).?.code;
12821285 if (needed_size != segment.size) {
12831286 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
12841287 if (needed_size > segment.size) {
......@@ -1337,10 +1340,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
13371340 },
13381341 .wasm => {
13391342 const wasm_file = file.cast(File.Wasm).?;
1340 const segment_index = wasm_file.getDebugLineIndex() catch unreachable;
1343 const segment_index = wasm_file.debug_line_index.?;
13411344 const segment = wasm_file.segments.items[segment_index];
13421345 const offset = segment.offset + decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
1343 mem.copy(u8, wasm_file.debug_line.items[offset..], &data);
1346 mem.copy(u8, wasm_file.atoms.get(segment_index).?.code.items[offset..], &data);
13441347 },
13451348 else => unreachable,
13461349 }
......@@ -1576,8 +1579,10 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
15761579 },
15771580 .wasm => {
15781581 const wasm_file = file.cast(File.Wasm).?;
1579 try wasm_file.debug_abbrev.resize(wasm_file.base.allocator, needed_size);
1580 mem.copy(u8, wasm_file.debug_abbrev.items, &abbrev_buf);
1582 const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_abbrev_index);
1583 const debug_abbrev = &wasm_file.atoms.get(segment_index).?.code;
1584 try debug_abbrev.resize(wasm_file.base.allocator, needed_size);
1585 mem.copy(u8, debug_abbrev.items, &abbrev_buf);
15811586 },
15821587 else => unreachable,
15831588 }
......@@ -1687,7 +1692,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
16871692 },
16881693 .wasm => {
16891694 const wasm_file = file.cast(File.Wasm).?;
1690 try writeDbgInfoNopsToArrayList(self.allocator, &wasm_file.debug_info, 0, 0, di_buf.items, jmp_amt, false);
1695 const segment_index = wasm_file.debug_info_index.?;
1696 const debug_info = &wasm_file.atoms.get(segment_index).?.code;
1697 try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
16911698 },
16921699 else => unreachable,
16931700 }
......@@ -2016,8 +2023,10 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
20162023 },
20172024 .wasm => {
20182025 const wasm_file = file.cast(File.Wasm).?;
2019 try wasm_file.debug_aranges.resize(wasm_file.base.allocator, needed_size);
2020 mem.copy(u8, wasm_file.debug_aranges.items, di_buf.items);
2026 const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_ranges_index);
2027 const debug_ranges = &wasm_file.atoms.get(segment_index).?.code;
2028 try debug_ranges.resize(wasm_file.base.allocator, needed_size);
2029 mem.copy(u8, debug_ranges.items, di_buf.items);
20212030 },
20222031 else => unreachable,
20232032 }
......@@ -2139,7 +2148,9 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
21392148 },
21402149 .wasm => {
21412150 const wasm_file = file.cast(File.Wasm).?;
2142 writeDbgLineNopsBuffered(wasm_file.debug_line.items, 0, 0, di_buf.items, jmp_amt);
2151 const segment_index = wasm_file.debug_line_index.?;
2152 const debug_line = wasm_file.atoms.get(segment_index).?.code;
2153 writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
21432154 },
21442155 else => unreachable,
21452156 }
......@@ -2287,7 +2298,9 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
22872298 },
22882299 .wasm => {
22892300 const wasm_file = file.cast(File.Wasm).?;
2290 mem.copy(u8, wasm_file.debug_info.items[reloc.atom.off + reloc.offset ..], &buf);
2301 const segment_index = wasm_file.debug_info_index.?;
2302 const debug_info = wasm_file.atoms.get(segment_index).?.code;
2303 mem.copy(u8, debug_info.items[reloc.atom.off + reloc.offset ..], &buf);
22912304 },
22922305 else => unreachable,
22932306 }
src/link/Wasm.zig+16-41
......@@ -103,16 +103,6 @@ string_table: StringTable = .{},
103103/// Debug information for wasm
104104dwarf: ?Dwarf = null,
105105
106// *debug information* //
107/// Contains all bytes for the '.debug_info' section
108debug_info: std.ArrayListUnmanaged(u8) = .{},
109/// Contains all bytes for the '.debug_line' section
110debug_line: std.ArrayListUnmanaged(u8) = .{},
111/// Contains all bytes for the '.debug_abbrev' section
112debug_abbrev: std.ArrayListUnmanaged(u8) = .{},
113/// Contains all bytes for the '.debug_ranges' section
114debug_aranges: std.ArrayListUnmanaged(u8) = .{},
115
116106// Output sections
117107/// Output type section
118108func_types: std.ArrayListUnmanaged(wasm.Type) = .{},
......@@ -716,11 +706,6 @@ pub fn deinit(self: *Wasm) void {
716706 if (self.dwarf) |*dwarf| {
717707 dwarf.deinit();
718708 }
719
720 self.debug_info.deinit(gpa);
721 self.debug_line.deinit(gpa);
722 self.debug_abbrev.deinit(gpa);
723 self.debug_aranges.deinit(gpa);
724709}
725710
726711pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
......@@ -1983,32 +1968,22 @@ fn populateErrorNameTable(self: *Wasm) !void {
19831968 try self.parseAtom(names_atom, .{ .data = .read_only });
19841969}
19851970
1986pub fn getDebugInfoIndex(self: *Wasm) !u32 {
1987 assert(self.dwarf != null);
1988 return self.debug_info_index orelse {
1989 self.debug_info_index = @intCast(u32, self.segments.items.len);
1990 const segment = try self.segments.addOne(self.base.allocator);
1991 segment.* = .{
1992 .size = 0,
1993 .offset = 0,
1994 // debug sections always have alignment '1'
1995 .alignment = 1,
1996 };
1997 return self.debug_info_index.?;
1998 };
1999}
2000
2001pub fn getDebugLineIndex(self: *Wasm) !u32 {
2002 assert(self.dwarf != null);
2003 return self.debug_line_index orelse {
2004 self.debug_line_index = @intCast(u32, self.segments.items.len);
2005 const segment = try self.segments.addOne(self.base.allocator);
2006 segment.* = .{
2007 .size = 0,
2008 .offset = 0,
2009 .alignment = 1,
2010 };
2011 return self.debug_line_index.?;
1971/// From a given index variable, returns it value if set.
1972/// When not set, initialises a new segment, sets the index,
1973/// and returns it value.
1974/// When a new segment is initialised. It also creates an atom.
1975pub fn getOrSetDebugIndex(self: *Wasm, index: *?u32) !u32 {
1976 return (index.*) orelse {
1977 const new_index = @intCast(u32, self.segments.items.len);
1978 index.* = new_index;
1979 try self.appendDummySegment();
1980
1981 const atom = try self.base.allocator.create(Atom);
1982 atom.* = Atom.empty;
1983 atom.alignment = 1; // debug sections are always 1-byte-aligned
1984 try self.managed_atoms.append(self.base.allocator, atom);
1985 try self.atoms.put(self.base.allocator, new_index, atom);
1986 return new_index;
20121987 };
20131988}
20141989