Commit b2718e213e

Luuk de Gram <luuk@degram.dev>
2022-09-02 21:13:59
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.
1 parent 46c932a
Changed files (2)
src/link/Dwarf.zig
@@ -861,7 +861,9 @@ pub fn commitDeclState(
                             },
                             .wasm => {
                                 const wasm_file = file.cast(File.Wasm).?;
-                                writeDbgLineNopsBuffered(wasm_file.debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
+                                const segment_index = wasm_file.debug_line_index.?;
+                                const debug_line = wasm_file.atoms.get(segment_index).?.code;
+                                writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
                             },
                             else => unreachable,
                         }
@@ -972,9 +974,9 @@ pub fn commitDeclState(
                 },
                 .wasm => {
                     const wasm_file = file.cast(File.Wasm).?;
-                    const segment_index = try wasm_file.getDebugLineIndex();
+                    const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_line_index);
                     const segment = &wasm_file.segments.items[segment_index];
-                    const debug_line = &wasm_file.debug_line;
+                    const debug_line = &wasm_file.atoms.get(segment_index).?.code;
                     if (needed_size != segment.size) {
                         log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
                         if (needed_size > segment.size) {
@@ -1146,10 +1148,11 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
                     },
                     .wasm => {
                         const wasm_file = file.cast(File.Wasm).?;
-                        const segment_index = try wasm_file.getDebugInfoIndex();
+                        const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_info_index);
                         const segment = &wasm_file.segments.items[segment_index];
+                        const debug_info = &wasm_file.atoms.get(segment_index).?.code;
                         const offset = segment.offset + atom.off;
-                        try writeDbgInfoNopsToArrayList(gpa, &wasm_file.debug_info, offset, 0, &.{0}, atom.len, false);
+                        try writeDbgInfoNopsToArrayList(gpa, debug_info, offset, 0, &.{0}, atom.len, false);
                     },
                     else => unreachable,
                 }
@@ -1276,9 +1279,9 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            const segment_index = try wasm_file.getDebugInfoIndex();
+            const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_info_index);
             const segment = &wasm_file.segments.items[segment_index];
-            const debug_info = &wasm_file.debug_info;
+            const debug_info = &wasm_file.atoms.get(segment_index).?.code;
             if (needed_size != segment.size) {
                 log.debug(" needed size does not equal allocated size: {d}", .{needed_size});
                 if (needed_size > segment.size) {
@@ -1337,10 +1340,10 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            const segment_index = wasm_file.getDebugLineIndex() catch unreachable;
+            const segment_index = wasm_file.debug_line_index.?;
             const segment = wasm_file.segments.items[segment_index];
             const offset = segment.offset + decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
-            mem.copy(u8, wasm_file.debug_line.items[offset..], &data);
+            mem.copy(u8, wasm_file.atoms.get(segment_index).?.code.items[offset..], &data);
         },
         else => unreachable,
     }
@@ -1576,8 +1579,10 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            try wasm_file.debug_abbrev.resize(wasm_file.base.allocator, needed_size);
-            mem.copy(u8, wasm_file.debug_abbrev.items, &abbrev_buf);
+            const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_abbrev_index);
+            const debug_abbrev = &wasm_file.atoms.get(segment_index).?.code;
+            try debug_abbrev.resize(wasm_file.base.allocator, needed_size);
+            mem.copy(u8, debug_abbrev.items, &abbrev_buf);
         },
         else => unreachable,
     }
@@ -1687,7 +1692,9 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            try writeDbgInfoNopsToArrayList(self.allocator, &wasm_file.debug_info, 0, 0, di_buf.items, jmp_amt, false);
+            const segment_index = wasm_file.debug_info_index.?;
+            const debug_info = &wasm_file.atoms.get(segment_index).?.code;
+            try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
         },
         else => unreachable,
     }
@@ -2016,8 +2023,10 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            try wasm_file.debug_aranges.resize(wasm_file.base.allocator, needed_size);
-            mem.copy(u8, wasm_file.debug_aranges.items, di_buf.items);
+            const segment_index = try wasm_file.getOrSetDebugIndex(&wasm_file.debug_ranges_index);
+            const debug_ranges = &wasm_file.atoms.get(segment_index).?.code;
+            try debug_ranges.resize(wasm_file.base.allocator, needed_size);
+            mem.copy(u8, debug_ranges.items, di_buf.items);
         },
         else => unreachable,
     }
@@ -2139,7 +2148,9 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
         },
         .wasm => {
             const wasm_file = file.cast(File.Wasm).?;
-            writeDbgLineNopsBuffered(wasm_file.debug_line.items, 0, 0, di_buf.items, jmp_amt);
+            const segment_index = wasm_file.debug_line_index.?;
+            const debug_line = wasm_file.atoms.get(segment_index).?.code;
+            writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
         },
         else => unreachable,
     }
@@ -2287,7 +2298,9 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
                 },
                 .wasm => {
                     const wasm_file = file.cast(File.Wasm).?;
-                    mem.copy(u8, wasm_file.debug_info.items[reloc.atom.off + reloc.offset ..], &buf);
+                    const segment_index = wasm_file.debug_info_index.?;
+                    const debug_info = wasm_file.atoms.get(segment_index).?.code;
+                    mem.copy(u8, debug_info.items[reloc.atom.off + reloc.offset ..], &buf);
                 },
                 else => unreachable,
             }
src/link/Wasm.zig
@@ -103,16 +103,6 @@ string_table: StringTable = .{},
 /// Debug information for wasm
 dwarf: ?Dwarf = null,
 
-// *debug information* //
-/// Contains all bytes for the '.debug_info' section
-debug_info: std.ArrayListUnmanaged(u8) = .{},
-/// Contains all bytes for the '.debug_line' section
-debug_line: std.ArrayListUnmanaged(u8) = .{},
-/// Contains all bytes for the '.debug_abbrev' section
-debug_abbrev: std.ArrayListUnmanaged(u8) = .{},
-/// Contains all bytes for the '.debug_ranges' section
-debug_aranges: std.ArrayListUnmanaged(u8) = .{},
-
 // Output sections
 /// Output type section
 func_types: std.ArrayListUnmanaged(wasm.Type) = .{},
@@ -716,11 +706,6 @@ pub fn deinit(self: *Wasm) void {
     if (self.dwarf) |*dwarf| {
         dwarf.deinit();
     }
-
-    self.debug_info.deinit(gpa);
-    self.debug_line.deinit(gpa);
-    self.debug_abbrev.deinit(gpa);
-    self.debug_aranges.deinit(gpa);
 }
 
 pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
@@ -1983,32 +1968,22 @@ fn populateErrorNameTable(self: *Wasm) !void {
     try self.parseAtom(names_atom, .{ .data = .read_only });
 }
 
-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.?;
+/// From a given index variable, returns it value if set.
+/// When not set, initialises a new segment, sets the index,
+/// and returns it value.
+/// When a new segment is initialised. It also creates an atom.
+pub fn getOrSetDebugIndex(self: *Wasm, index: *?u32) !u32 {
+    return (index.*) orelse {
+        const new_index = @intCast(u32, self.segments.items.len);
+        index.* = new_index;
+        try self.appendDummySegment();
+
+        const atom = try self.base.allocator.create(Atom);
+        atom.* = Atom.empty;
+        atom.alignment = 1; // debug sections are always 1-byte-aligned
+        try self.managed_atoms.append(self.base.allocator, atom);
+        try self.atoms.put(self.base.allocator, new_index, atom);
+        return new_index;
     };
 }