aboutsummaryrefslogtreecommitdiff
path: root/src/link/Dwarf.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-12-06 19:29:23 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-12-09 09:24:25 +0100
commitf5c764d8923d301bb7e46b50cb034285640fcca2 (patch)
treee573f5faca2995d766b56e1e001989a343ff08b3 /src/link/Dwarf.zig
parent4c4821d9939447d65966b897a5780e39eb22334b (diff)
downloadzig-f5c764d8923d301bb7e46b50cb034285640fcca2.tar.gz
zig-f5c764d8923d301bb7e46b50cb034285640fcca2.zip
dwarf: track source files via *const Module.File pointers
Diffstat (limited to 'src/link/Dwarf.zig')
-rw-r--r--src/link/Dwarf.zig267
1 files changed, 141 insertions, 126 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index e4d6b8ae05..12b34a070b 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -22,7 +22,7 @@ const Value = @import("../value.zig").Value;
const Type = @import("../type.zig").Type;
allocator: Allocator,
-tag: File.Tag,
+bin_file: *File,
ptr_width: PtrWidth,
target: std.Target,
@@ -44,10 +44,9 @@ abbrev_table_offset: ?u64 = null,
/// Table of debug symbol names.
strtab: std.ArrayListUnmanaged(u8) = .{},
-file_names_buffer: std.ArrayListUnmanaged(u8) = .{},
-file_names: std.ArrayListUnmanaged(u32) = .{},
-file_names_free_list: std.ArrayListUnmanaged(u28) = .{},
-file_names_lookup: std.AutoHashMapUnmanaged(*Module.File, u28) = .{},
+di_files: std.ArrayListUnmanaged(DIFile) = .{},
+di_files_free_list: std.ArrayListUnmanaged(u28) = .{},
+di_files_lookup: std.AutoHashMapUnmanaged(*const Module.File, u28) = .{},
/// List of atoms that are owned directly by the DWARF module.
/// TODO convert links in DebugInfoAtom into indices and make
@@ -56,6 +55,15 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},
global_abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
+const DIFile = struct {
+ file_source: *const Module.File,
+ ref_count: u32,
+
+ fn getFullPath(dif: DIFile, allocator: Allocator) ![]const u8 {
+ return dif.file_source.fullPath(allocator);
+ }
+};
+
pub const Atom = struct {
/// Previous/next linked list pointers.
/// This is the linked list node for this Decl's corresponding .debug_info tag.
@@ -892,7 +900,7 @@ const min_nop_size = 2;
/// actual_capacity + (actual_capacity / ideal_factor)
const ideal_factor = 3;
-pub fn init(allocator: Allocator, tag: File.Tag, target: std.Target) Dwarf {
+pub fn init(allocator: Allocator, bin_file: *File, target: std.Target) Dwarf {
const ptr_width: PtrWidth = switch (target.cpu.arch.ptrBitWidth()) {
0...32 => .p32,
33...64 => .p64,
@@ -900,7 +908,7 @@ pub fn init(allocator: Allocator, tag: File.Tag, target: std.Target) Dwarf {
};
return Dwarf{
.allocator = allocator,
- .tag = tag,
+ .bin_file = bin_file,
.ptr_width = ptr_width,
.target = target,
};
@@ -911,10 +919,9 @@ pub fn deinit(self: *Dwarf) void {
self.dbg_line_fn_free_list.deinit(gpa);
self.atom_free_list.deinit(gpa);
self.strtab.deinit(gpa);
- self.file_names_buffer.deinit(gpa);
- self.file_names.deinit(gpa);
- self.file_names_free_list.deinit(gpa);
- self.file_names_lookup.deinit(gpa);
+ self.di_files.deinit(gpa);
+ self.di_files_free_list.deinit(gpa);
+ self.di_files_lookup.deinit(gpa);
self.global_abbrev_relocs.deinit(gpa);
for (self.managed_atoms.items) |atom| {
@@ -977,7 +984,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len);
// Once we support more than one source file, this will have the ability to be more
// than one possible value.
- const file_index = try self.addFileName(mod, decl_index);
+ const file_index = try self.addDIFile(mod, decl_index);
leb128.writeUnsignedFixed(
4,
dbg_line_buffer.addManyAsArrayAssumeCapacity(4),
@@ -1008,7 +1015,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
dbg_info_buffer.items.len += 4; // DW.AT.high_pc, DW.FORM.data4
//
if (fn_ret_has_bits) {
- const atom = getDbgInfoAtom(self.tag, mod, decl_index);
+ const atom = getDbgInfoAtom(self.bin_file.tag, mod, decl_index);
try decl_state.addTypeRelocGlobal(atom, fn_ret_type, @intCast(u32, dbg_info_buffer.items.len));
dbg_info_buffer.items.len += 4; // DW.AT.type, DW.FORM.ref4
}
@@ -1026,7 +1033,6 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
pub fn commitDeclState(
self: *Dwarf,
- file: *File,
module: *Module,
decl_index: Module.Decl.Index,
sym_addr: u64,
@@ -1082,7 +1088,7 @@ pub fn commitDeclState(
// This logic is nearly identical to the logic below in `updateDeclDebugInfo` for
// `TextBlock` and the .debug_info. If you are editing this logic, you
// probably need to edit that logic too.
- const src_fn = switch (self.tag) {
+ const src_fn = switch (self.bin_file.tag) {
.elf => &decl.fn_link.elf,
.macho => &decl.fn_link.macho,
.wasm => &decl.fn_link.wasm.src_fn,
@@ -1103,22 +1109,22 @@ pub fn commitDeclState(
next.prev = src_fn.prev;
src_fn.next = null;
// Populate where it used to be with NOPs.
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_line_sect = &elf_file.sections.items[elf_file.debug_line_section_index.?];
const file_pos = debug_line_sect.sh_offset + src_fn.off;
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, src_fn.len);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_line_sect = &d_sym.sections.items[d_sym.debug_line_section_index.?];
const file_pos = debug_line_sect.offset + src_fn.off;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, &[0]u8{}, src_fn.len);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_line = wasm_file.debug_line_atom.?.code;
writeDbgLineNopsBuffered(debug_line.items, src_fn.off, 0, &.{}, src_fn.len);
},
@@ -1156,9 +1162,9 @@ pub fn commitDeclState(
// We only have support for one compilation unit so far, so the offsets are directly
// from the .debug_line section.
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_line_sect = &elf_file.sections.items[elf_file.debug_line_section_index.?];
if (needed_size != debug_line_sect.sh_size) {
if (needed_size > elf_file.allocatedSize(debug_line_sect.sh_offset)) {
@@ -1193,7 +1199,7 @@ pub fn commitDeclState(
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_line_sect = &d_sym.sections.items[d_sym.debug_line_section_index.?];
if (needed_size != debug_line_sect.size) {
@@ -1228,7 +1234,7 @@ pub fn commitDeclState(
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const atom = wasm_file.debug_line_atom.?;
const debug_line = &atom.code;
const segment_size = debug_line.items.len;
@@ -1261,7 +1267,7 @@ pub fn commitDeclState(
if (dbg_info_buffer.items.len == 0)
return;
- const atom = getDbgInfoAtom(self.tag, module, decl_index);
+ const atom = getDbgInfoAtom(self.bin_file.tag, module, decl_index);
if (decl_state.abbrev_table.items.len > 0) {
// Now we emit the .debug_info types of the Decl. These will count towards the size of
// the buffer, so we have to do it before computing the offset, and we can't perform the actual
@@ -1288,7 +1294,7 @@ pub fn commitDeclState(
}
log.debug("updateDeclDebugInfoAllocation for '{s}'", .{decl.name});
- try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
+ try self.updateDeclDebugInfoAllocation(atom, @intCast(u32, dbg_info_buffer.items.len));
while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
if (reloc.target) |target| {
@@ -1333,9 +1339,9 @@ pub fn commitDeclState(
}
while (decl_state.exprloc_relocs.popOrNull()) |reloc| {
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
try d_sym.relocs.append(d_sym.allocator, .{
.type = switch (reloc.type) {
@@ -1353,10 +1359,10 @@ pub fn commitDeclState(
}
log.debug("writeDeclDebugInfo for '{s}", .{decl.name});
- try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
+ try self.writeDeclDebugInfo(atom, dbg_info_buffer.items);
}
-fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u32) !void {
+fn updateDeclDebugInfoAllocation(self: *Dwarf, atom: *Atom, len: u32) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -1379,22 +1385,22 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
next.prev = atom.prev;
atom.next = null;
// Populate where it used to be with NOPs.
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?];
const file_pos = debug_info_sect.sh_offset + atom.off;
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, &[0]u8{}, atom.len, false);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_info_sect = &d_sym.sections.items[d_sym.debug_info_section_index.?];
const file_pos = debug_info_sect.offset + atom.off;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, &[0]u8{}, atom.len, false);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info = &wasm_file.debug_info_atom.?.code;
try writeDbgInfoNopsToArrayList(gpa, debug_info, atom.off, 0, &.{0}, atom.len, false);
},
@@ -1425,7 +1431,7 @@ fn updateDeclDebugInfoAllocation(self: *Dwarf, file: *File, atom: *Atom, len: u3
}
}
-fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []const u8) !void {
+fn writeDeclDebugInfo(self: *Dwarf, atom: *Atom, dbg_info_buf: []const u8) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -1445,9 +1451,9 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
// We only have support for one compilation unit so far, so the offsets are directly
// from the .debug_info section.
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?];
if (needed_size != debug_info_sect.sh_size) {
if (needed_size > elf_file.allocatedSize(debug_info_sect.sh_offset)) {
@@ -1483,7 +1489,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_info_sect = &d_sym.sections.items[d_sym.debug_info_section_index.?];
if (needed_size != debug_info_sect.size) {
@@ -1519,7 +1525,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const info_atom = wasm_file.debug_info_atom.?;
const debug_info = &info_atom.code;
const segment_size = debug_info.items.len;
@@ -1549,7 +1555,7 @@ fn writeDeclDebugInfo(self: *Dwarf, file: *File, atom: *Atom, dbg_info_buf: []co
}
}
-pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl) !void {
+pub fn updateDeclLineNumber(self: *Dwarf, decl: *const Module.Decl) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -1563,22 +1569,22 @@ pub fn updateDeclLineNumber(self: *Dwarf, file: *File, decl: *const Module.Decl)
var data: [4]u8 = undefined;
leb128.writeUnsignedFixed(4, &data, line);
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const shdr = elf_file.sections.items[elf_file.debug_line_section_index.?];
const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();
try elf_file.base.file.?.pwriteAll(&data, file_pos);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = macho_file.d_sym.?;
const sect = d_sym.sections.items[d_sym.debug_line_section_index.?];
const file_pos = sect.offset + decl.fn_link.macho.off + self.getRelocDbgLineOff();
try d_sym.file.pwriteAll(&data, file_pos);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const offset = decl.fn_link.wasm.src_fn.off + self.getRelocDbgLineOff();
const atom = wasm_file.debug_line_atom.?;
mem.copy(u8, atom.code.items[offset..], &data);
@@ -1615,7 +1621,7 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {
// TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing
// is desired for both.
const gpa = self.allocator;
- const fn_link = switch (self.tag) {
+ const fn_link = switch (self.bin_file.tag) {
.elf => &decl.fn_link.elf,
.macho => &decl.fn_link.macho,
.wasm => &decl.fn_link.wasm.src_fn,
@@ -1641,9 +1647,19 @@ pub fn freeDecl(self: *Dwarf, decl: *Module.Decl) void {
if (self.dbg_line_fn_last == fn_link) {
self.dbg_line_fn_last = fn_link.prev;
}
+
+ const file_source = decl.getFileScope();
+ if (self.di_files_lookup.get(file_source)) |dif_index| {
+ const dif = &self.di_files.items[dif_index];
+ dif.ref_count -= 1;
+ if (dif.ref_count == 0) {
+ self.di_files_free_list.append(gpa, dif_index) catch {};
+ }
+ _ = self.di_files_lookup.remove(file_source);
+ }
}
-pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
+pub fn writeDbgAbbrev(self: *Dwarf) !void {
// These are LEB encoded but since the values are all less than 127
// we can simply append these bytes.
const abbrev_buf = [_]u8{
@@ -1777,9 +1793,9 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
self.abbrev_table_offset = abbrev_offset;
const needed_size = abbrev_buf.len;
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_abbrev_sect = &elf_file.sections.items[elf_file.debug_abbrev_section_index.?];
const allocated_size = elf_file.allocatedSize(debug_abbrev_sect.sh_offset);
if (needed_size > allocated_size) {
@@ -1796,7 +1812,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const dwarf_segment = d_sym.segments.items[d_sym.dwarf_segment_cmd_index.?];
const debug_abbrev_sect = &d_sym.sections.items[d_sym.debug_abbrev_section_index.?];
@@ -1816,7 +1832,7 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
try d_sym.file.pwriteAll(&abbrev_buf, file_pos);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_abbrev = &wasm_file.debug_abbrev_atom.?.code;
try debug_abbrev.resize(wasm_file.base.allocator, needed_size);
mem.copy(u8, debug_abbrev.items, &abbrev_buf);
@@ -1830,7 +1846,7 @@ fn dbgInfoHeaderBytes(self: *Dwarf) usize {
return 120;
}
-pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u64, high_pc: u64) !void {
+pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u64) !void {
// If this value is null it means there is an error in the module;
// leave debug_info_header_dirty=true.
const first_dbg_info_off = self.getDebugInfoOff() orelse return;
@@ -1842,7 +1858,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
defer di_buf.deinit();
const target_endian = self.target.cpu.arch.endian();
- const init_len_size: usize = if (self.tag == .macho)
+ const init_len_size: usize = if (self.bin_file.tag == .macho)
4
else switch (self.ptr_width) {
.p32 => @as(usize, 4),
@@ -1856,7 +1872,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
// +1 for the final 0 that ends the compilation unit children.
const dbg_info_end = self.getDebugInfoEnd().? + 1;
const init_len = dbg_info_end - after_init_len;
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len));
} else switch (self.ptr_width) {
.p32 => {
@@ -1869,7 +1885,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
}
mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version
const abbrev_offset = self.abbrev_table_offset.?;
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, abbrev_offset));
di_buf.appendAssumeCapacity(8); // address size
} else switch (self.ptr_width) {
@@ -1888,7 +1904,7 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
const producer_strp = try self.makeString(link.producer_string);
di_buf.appendAssumeCapacity(@enumToInt(AbbrevKind.compile_unit));
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // DW.AT.stmt_list, DW.FORM.sec_offset
mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), low_pc);
mem.writeIntLittle(u64, di_buf.addManyAsArrayAssumeCapacity(8), high_pc);
@@ -1913,22 +1929,22 @@ pub fn writeDbgInfoHeader(self: *Dwarf, file: *File, module: *Module, low_pc: u6
@panic("TODO: handle .debug_info header exceeding its padding");
}
const jmp_amt = first_dbg_info_off - di_buf.items.len;
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_info_sect = elf_file.sections.items[elf_file.debug_info_section_index.?];
const file_pos = debug_info_sect.sh_offset;
try pwriteDbgInfoNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt, false);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_info_sect = d_sym.sections.items[d_sym.debug_info_section_index.?];
const file_pos = debug_info_sect.offset;
try pwriteDbgInfoNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt, false);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info = &wasm_file.debug_info_atom.?.code;
try writeDbgInfoNopsToArrayList(self.allocator, debug_info, 0, 0, di_buf.items, jmp_amt, false);
},
@@ -2158,9 +2174,9 @@ fn writeDbgInfoNopsToArrayList(
}
}
-pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
+pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
const target_endian = self.target.cpu.arch.endian();
- const init_len_size: usize = if (self.tag == .macho)
+ const init_len_size: usize = if (self.bin_file.tag == .macho)
4
else switch (self.ptr_width) {
.p32 => @as(usize, 4),
@@ -2182,7 +2198,7 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 2, target_endian); // version
// When more than one compilation unit is supported, this will be the offset to it.
// For now it is always at offset 0 in .debug_info.
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // __debug_info offset
} else {
self.writeAddrAssumeCapacity(&di_buf, 0); // .debug_info offset
@@ -2205,7 +2221,7 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
// Go back and populate the initial length.
const init_len = di_buf.items.len - after_init_len;
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.items[init_len_index..][0..4], @intCast(u32, init_len));
} else switch (self.ptr_width) {
.p32 => {
@@ -2220,9 +2236,9 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
}
const needed_size = di_buf.items.len;
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_aranges_sect = &elf_file.sections.items[elf_file.debug_aranges_section_index.?];
const allocated_size = elf_file.allocatedSize(debug_aranges_sect.sh_offset);
if (needed_size > allocated_size) {
@@ -2238,7 +2254,7 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const dwarf_seg = d_sym.segments.items[d_sym.dwarf_segment_cmd_index.?];
const debug_aranges_sect = &d_sym.sections.items[d_sym.debug_aranges_section_index.?];
@@ -2258,7 +2274,7 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
try d_sym.file.pwriteAll(di_buf.items, file_pos);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_ranges = &wasm_file.debug_ranges_atom.?.code;
try debug_ranges.resize(wasm_file.base.allocator, needed_size);
mem.copy(u8, debug_ranges.items, di_buf.items);
@@ -2267,10 +2283,10 @@ pub fn writeDbgAranges(self: *Dwarf, file: *File, addr: u64, size: u64) !void {
}
}
-pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
+pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
const ptr_width_bytes: u8 = self.ptrWidthBytes();
const target_endian = self.target.cpu.arch.endian();
- const init_len_size: usize = if (self.tag == .macho)
+ const init_len_size: usize = if (self.bin_file.tag == .macho)
4
else switch (self.ptr_width) {
.p32 => @as(usize, 4),
@@ -2293,7 +2309,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
// not including the initial length itself.
const after_init_len = di_buf.items.len + init_len_size;
const init_len = dbg_line_prg_end - after_init_len;
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @intCast(u32, init_len));
} else switch (self.ptr_width) {
.p32 => {
@@ -2312,7 +2328,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
// Therefore we rely on the NOP jump at the beginning of the Line Number Program for
// padding rather than this field.
const before_header_len = di_buf.items.len;
- di_buf.items.len += if (self.tag == .macho) @sizeOf(u32) else ptr_width_bytes; // We will come back and write this.
+ di_buf.items.len += if (self.bin_file.tag == .macho) @sizeOf(u32) else ptr_width_bytes; // We will come back and write this.
const after_header_len = di_buf.items.len;
const opcode_base = DW.LNS.set_isa + 1;
@@ -2340,20 +2356,12 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
1, // `DW.LNS.set_isa`
0, // include_directories (none except the compilation unit cwd)
});
- // // file_names[0]
- // di_buf.appendSliceAssumeCapacity(module.root_pkg.root_src_path); // relative path name
- // di_buf.appendSliceAssumeCapacity(&[_]u8{
- // 0, // null byte for the relative path name
- // 0, // directory_index
- // 0, // mtime (TODO supply this)
- // 0, // file size bytes (TODO supply this)
- // 0, // file_names sentinel
- // });
-
- for (self.file_names.items) |off, i| {
- const file_name = self.getFileName(off);
- log.debug("file_name[{d}] = {s}", .{ i + 1, file_name });
- di_buf.appendSliceAssumeCapacity(file_name);
+
+ for (self.di_files.items) |dif, i| {
+ const full_path = try dif.getFullPath(self.allocator);
+ defer self.allocator.free(full_path);
+ log.debug("adding new file name at {d} of '{s}'", .{ i + 1, full_path });
+ di_buf.appendSliceAssumeCapacity(full_path);
di_buf.appendSliceAssumeCapacity(&[_]u8{
0, // null byte for the relative path name
0, // directory_index
@@ -2364,7 +2372,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
di_buf.appendAssumeCapacity(0); // file names sentinel
const header_len = di_buf.items.len - after_header_len;
- if (self.tag == .macho) {
+ if (self.bin_file.tag == .macho) {
mem.writeIntLittle(u32, di_buf.items[before_header_len..][0..4], @intCast(u32, header_len));
} else switch (self.ptr_width) {
.p32 => {
@@ -2381,22 +2389,22 @@ pub fn writeDbgLineHeader(self: *Dwarf, file: *File, module: *Module) !void {
@panic("TODO: handle .debug_line header exceeding its padding");
}
const jmp_amt = dbg_line_prg_off - di_buf.items.len;
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_line_sect = elf_file.sections.items[elf_file.debug_line_section_index.?];
const file_pos = debug_line_sect.sh_offset;
try pwriteDbgLineNops(elf_file.base.file.?, file_pos, 0, di_buf.items, jmp_amt);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_line_sect = d_sym.sections.items[d_sym.debug_line_section_index.?];
const file_pos = debug_line_sect.offset;
try pwriteDbgLineNops(d_sym.file, file_pos, 0, di_buf.items, jmp_amt);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_line = wasm_file.debug_line_atom.?.code;
writeDbgLineNopsBuffered(debug_line.items, 0, 0, di_buf.items, jmp_amt);
},
@@ -2436,15 +2444,21 @@ fn dbgLineNeededHeaderBytes(self: Dwarf, module: *Module) u32 {
const directory_entry_format_count = 1;
const file_name_entry_format_count = 1;
const directory_count = 1;
- const file_name_count = self.file_names.items.len;
+ const file_name_count = self.di_files.items.len;
const root_src_dir_path_len = if (module.root_pkg.root_src_directory.path) |p| p.len else 1; // "."
+ var file_names_len: usize = 0;
+ for (self.di_files.items) |dif| {
+ const dir_path = dif.file_source.pkg.root_src_directory.path orelse ".";
+ file_names_len += dir_path.len + dif.file_source.sub_file_path.len + 1;
+ }
+
return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 +
directory_count * 8 + file_name_count * 8 +
// These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like
// because of a workaround for readelf and gdb failing to understand DWARFv5 correctly.
root_src_dir_path_len +
- self.file_names_buffer.items.len);
+ file_names_len);
}
/// The reloc offset for the line offset of a function from the previous function's line.
@@ -2476,7 +2490,7 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
std.math.maxInt(@TypeOf(actual_size));
}
-pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
+pub fn flushModule(self: *Dwarf, module: *Module) !void {
if (self.global_abbrev_relocs.items.len > 0) {
const gpa = self.allocator;
var arena_alloc = std.heap.ArenaAllocator.init(gpa);
@@ -2507,19 +2521,19 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
try self.managed_atoms.append(gpa, atom);
log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
- try self.updateDeclDebugInfoAllocation(file, atom, @intCast(u32, dbg_info_buffer.items.len));
+ try self.updateDeclDebugInfoAllocation(atom, @intCast(u32, dbg_info_buffer.items.len));
log.debug("writeDeclDebugInfo in flushModule", .{});
- try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
+ try self.writeDeclDebugInfo(atom, dbg_info_buffer.items);
const file_pos = blk: {
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
const debug_info_sect = &elf_file.sections.items[elf_file.debug_info_section_index.?];
break :blk debug_info_sect.sh_offset;
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
const debug_info_sect = &d_sym.sections.items[d_sym.debug_info_section_index.?];
break :blk debug_info_sect.offset;
@@ -2534,18 +2548,18 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
mem.writeInt(u32, &buf, atom.off, self.target.cpu.arch.endian());
while (self.global_abbrev_relocs.popOrNull()) |reloc| {
- switch (self.tag) {
+ switch (self.bin_file.tag) {
.elf => {
- const elf_file = file.cast(File.Elf).?;
+ const elf_file = self.bin_file.cast(File.Elf).?;
try elf_file.base.file.?.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset);
},
.macho => {
- const macho_file = file.cast(File.MachO).?;
+ const macho_file = self.bin_file.cast(File.MachO).?;
const d_sym = &macho_file.d_sym.?;
try d_sym.file.pwriteAll(&buf, file_pos + reloc.atom.off + reloc.offset);
},
.wasm => {
- const wasm_file = file.cast(File.Wasm).?;
+ const wasm_file = self.bin_file.cast(File.Wasm).?;
const debug_info = wasm_file.debug_info_atom.?.code;
mem.copy(u8, debug_info.items[reloc.atom.off + reloc.offset ..], &buf);
},
@@ -2555,17 +2569,17 @@ pub fn flushModule(self: *Dwarf, file: *File, module: *Module) !void {
}
}
-fn allocateFileIndex(self: *Dwarf) !u28 {
- try self.file_names.ensureUnusedCapacity(self.allocator, 1);
+fn allocateDIFileIndex(self: *Dwarf) !u28 {
+ try self.di_files.ensureUnusedCapacity(self.allocator, 1);
const index = blk: {
- if (self.file_names_free_list.popOrNull()) |index| {
- log.debug(" (reusing file name index {d})", .{index});
+ if (self.di_files_free_list.popOrNull()) |index| {
+ log.debug(" (reusing DIFile index {d})", .{index});
break :blk index;
} else {
- const index = @intCast(u28, self.file_names.items.len);
- log.debug(" (allocating file name index {d})", .{index});
- _ = self.file_names.addOneAssumeCapacity();
+ const index = @intCast(u28, self.di_files.items.len);
+ log.debug(" (allocating DIFile index {d})", .{index});
+ _ = self.di_files.addOneAssumeCapacity();
break :blk index;
}
};
@@ -2573,27 +2587,28 @@ fn allocateFileIndex(self: *Dwarf) !u28 {
return index;
}
-fn addFileName(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
+fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
const decl = mod.declPtr(decl_index);
const file_scope = decl.getFileScope();
- if (self.file_names_lookup.get(file_scope)) |file_index| {
- return file_index;
- }
- const index = try self.allocateFileIndex();
- const file_name = try file_scope.fullPath(self.allocator);
- defer self.allocator.free(file_name);
- try self.file_names_buffer.ensureUnusedCapacity(self.allocator, file_name.len + 1);
- const off = @intCast(u32, self.file_names_buffer.items.len);
- self.file_names_buffer.appendSliceAssumeCapacity(file_name);
- self.file_names_buffer.appendAssumeCapacity(0);
- self.file_names.items[index] = off;
- try self.file_names_lookup.putNoClobber(self.allocator, file_scope, index);
- return index;
-}
+ const gop = try self.di_files_lookup.getOrPut(self.allocator, file_scope);
+ if (!gop.found_existing) {
+ gop.value_ptr.* = try self.allocateDIFileIndex();
+ self.di_files.items[gop.value_ptr.*] = .{
+ .file_source = file_scope,
+ .ref_count = 1,
+ };
-fn getFileName(self: Dwarf, off: u32) []const u8 {
- assert(off < self.file_names_buffer.items.len);
- return mem.sliceTo(@ptrCast([*:0]const u8, self.file_names_buffer.items.ptr) + off, 0);
+ switch (self.bin_file.tag) {
+ .elf => self.bin_file.cast(File.Elf).?.debug_line_header_dirty = true,
+ .macho => self.bin_file.cast(File.MachO).?.d_sym.?.debug_line_header_dirty = true,
+ .wasm => {},
+ else => unreachable,
+ }
+ } else {
+ const dif = &self.di_files.items[gop.value_ptr.*];
+ dif.ref_count += 1;
+ }
+ return gop.value_ptr.*;
}
fn addDbgInfoErrorSet(