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.
This commit is contained in:
Luuk de Gram 2022-09-02 21:13:59 +02:00
parent 46c932a2c9
commit b2718e213e
No known key found for this signature in database
GPG Key ID: A8CFE58E4DC7D664
2 changed files with 44 additions and 56 deletions

View File

@ -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,
}

View File

@ -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.?;
};
}
/// 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();
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.?;
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;
};
}