dwarf: move all dwarf into standalone module

Hook up Elf and MachO linkers to the new solution.
This commit is contained in:
Jakub Konka 2022-03-06 18:35:58 +01:00
parent 38c161afab
commit ba17552b4e
10 changed files with 1788 additions and 2487 deletions

View File

@ -4439,8 +4439,8 @@ pub fn clearDecl(
};
decl.fn_link = switch (mod.comp.bin_file.tag) {
.coff => .{ .coff = {} },
.elf => .{ .elf = link.File.Elf.SrcFn.empty },
.macho => .{ .macho = link.File.MachO.SrcFn.empty },
.elf => .{ .elf = link.File.Dwarf.SrcFn.empty },
.macho => .{ .macho = link.File.Dwarf.SrcFn.empty },
.plan9 => .{ .plan9 = {} },
.c => .{ .c = {} },
.wasm => .{ .wasm = link.File.Wasm.FnData.empty },
@ -4776,8 +4776,8 @@ pub fn allocateNewDecl(
},
.fn_link = switch (mod.comp.bin_file.tag) {
.coff => .{ .coff = {} },
.elf => .{ .elf = link.File.Elf.SrcFn.empty },
.macho => .{ .macho = link.File.MachO.SrcFn.empty },
.elf => .{ .elf = link.File.Dwarf.SrcFn.empty },
.macho => .{ .macho = link.File.Dwarf.SrcFn.empty },
.plan9 => .{ .plan9 = {} },
.c => .{ .c = {} },
.wasm => .{ .wasm = link.File.Wasm.FnData.empty },

View File

@ -409,7 +409,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
switch (self.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_info.ensureUnusedCapacity(3);
dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // ULEB128 dwarf expression length
reg.dwarfLocOp(),
@ -440,7 +440,7 @@ fn genArgDbgInfo(self: *Emit, inst: Air.Inst.Index, arg_index: u32) !void {
else => unreachable,
};
try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
try dbg_out.dbg_info.append(link.File.Dwarf.abbrev_parameter);
// Get length of the LEB128 stack offset
var counting_writer = std.io.countingWriter(std.io.null_writer);

View File

@ -1384,7 +1384,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32
switch (self.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_info.ensureUnusedCapacity(3);
dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // ULEB128 dwarf expression length
reg.dwarfLocOp(),

View File

@ -1019,14 +1019,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
switch (emit.debug_output) {
.dwarf => |dbg_out| {
try dbg_out.dbg_info.ensureUnusedCapacity(3);
// TODO this will go away once we pull DWARF into a cross-platform module.
if (emit.bin_file.cast(link.File.MachO)) |_| {
dbg_out.dbg_info.appendAssumeCapacity(link.File.MachO.DebugSymbols.abbrev_parameter);
} else if (emit.bin_file.cast(link.File.Elf)) |_| {
dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
} else return emit.fail("TODO DWARF in non-MachO and non-ELF backend", .{});
dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // ULEB128 dwarf expression length
reg.dwarfLocOp(),
@ -1049,14 +1042,7 @@ fn genArgDbgInfo(emit: *Emit, inst: Air.Inst.Index, mcv: MCValue, max_stack: u32
// for example when -fomit-frame-pointer is set.
const disp = @intCast(i32, max_stack) - off + 16;
try dbg_out.dbg_info.ensureUnusedCapacity(8);
// TODO this will go away once we pull DWARF into a cross-platform module.
if (emit.bin_file.cast(link.File.MachO)) |_| {
dbg_out.dbg_info.appendAssumeCapacity(link.File.MachO.DebugSymbols.abbrev_parameter);
} else if (emit.bin_file.cast(link.File.Elf)) |_| {
dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
} else return emit.fail("TODO DWARF in non-MachO and non-ELF backend", .{});
dbg_out.dbg_info.appendAssumeCapacity(link.File.Dwarf.abbrev_parameter);
const fixup = dbg_out.dbg_info.items.len;
dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, // we will backpatch it after we encode the displacement in LEB128

View File

@ -221,9 +221,9 @@ pub const File = struct {
};
pub const LinkFn = union {
elf: Elf.SrcFn,
elf: Dwarf.SrcFn,
coff: Coff.SrcFn,
macho: MachO.SrcFn,
macho: Dwarf.SrcFn,
plan9: void,
c: void,
wasm: Wasm.FnData,
@ -915,6 +915,7 @@ pub const File = struct {
pub const SpirV = @import("link/SpirV.zig");
pub const Wasm = @import("link/Wasm.zig");
pub const NvPtx = @import("link/NvPtx.zig");
pub const Dwarf = @import("link/Dwarf.zig");
};
pub fn determineMode(options: Options) fs.File.Mode {

1625
src/link/Dwarf.zig Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -295,26 +295,6 @@ pub const Export = struct {
sym_index: ?u32 = null,
};
pub const SrcFn = struct {
/// Offset from the beginning of the Debug Line Program header that contains this function.
off: u32,
/// Size of the line number program component belonging to this function, not
/// including padding.
len: u32,
/// Points to the previous and next neighbors, based on the offset from .debug_line.
/// This can be used to find, for example, the capacity of this `SrcFn`.
prev: ?*SrcFn,
next: ?*SrcFn,
pub const empty: SrcFn = .{
.off = 0,
.len = 0,
.prev = null,
.next = null,
};
};
pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
assert(options.object_format == .macho);
@ -376,6 +356,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
self.d_sym = .{
.base = self,
.dwarf = link.File.Dwarf.init(allocator, .macho, options.target),
.file = d_sym_file,
};
}
@ -3523,7 +3504,6 @@ fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection, owns_atom: bool)
i += 1;
}
}
// TODO process free list for dbg info just like we do above for vaddrs
if (self.atoms.getPtr(match)) |last_atom| {
if (last_atom.* == atom) {
@ -3536,16 +3516,6 @@ fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection, owns_atom: bool)
}
}
if (self.d_sym) |*d_sym| {
if (d_sym.dbg_info_decl_first == atom) {
d_sym.dbg_info_decl_first = atom.dbg_info_next;
}
if (d_sym.dbg_info_decl_last == atom) {
// TODO shrink the .debug_info section size here
d_sym.dbg_info_decl_last = atom.dbg_info_prev;
}
}
if (atom.prev) |prev| {
prev.next = atom.next;
@ -3564,18 +3534,8 @@ fn freeAtom(self: *MachO, atom: *Atom, match: MatchingSection, owns_atom: bool)
atom.next = null;
}
if (atom.dbg_info_prev) |prev| {
prev.dbg_info_next = atom.dbg_info_next;
// TODO the free list logic like we do for atoms above
} else {
atom.dbg_info_prev = null;
}
if (atom.dbg_info_next) |next| {
next.dbg_info_prev = atom.dbg_info_prev;
} else {
atom.dbg_info_next = null;
if (self.d_sym) |*d_sym| {
d_sym.dwarf.freeAtom(&atom.dbg_info_atom);
}
}
@ -3725,9 +3685,9 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
var debug_buffers_buf: DebugSymbols.DeclDebugBuffers = undefined;
var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined;
const debug_buffers = if (self.d_sym) |*d_sym| blk: {
debug_buffers_buf = try d_sym.initDeclDebugBuffers(self.base.allocator, module, decl);
debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl);
break :blk &debug_buffers_buf;
} else null;
defer {
@ -3766,7 +3726,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
if (debug_buffers) |db| {
if (self.d_sym) |*d_sym| {
try d_sym.commitDeclDebugInfo(self.base.allocator, module, decl, db);
try d_sym.commitDeclDebugInfo(module, decl, db);
}
}
@ -3805,9 +3765,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl: *Module.De
const atom = try self.createEmptyAtom(local_sym_index, @sizeOf(u64), math.log2(required_alignment));
try self.atom_by_index_table.putNoClobber(self.base.allocator, local_sym_index, atom);
const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
.none = .{},
}, .{
const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{
.parent_atom_index = local_sym_index,
});
const code = switch (res) {
@ -3869,9 +3827,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
var debug_buffers_buf: DebugSymbols.DeclDebugBuffers = undefined;
var debug_buffers_buf: link.File.Dwarf.DeclDebugBuffers = undefined;
const debug_buffers = if (self.d_sym) |*d_sym| blk: {
debug_buffers_buf = try d_sym.initDeclDebugBuffers(self.base.allocator, module, decl);
debug_buffers_buf = try d_sym.initDeclDebugInfo(module, decl);
break :blk &debug_buffers_buf;
} else null;
defer {
@ -4364,27 +4322,7 @@ pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
decl.link.macho.local_sym_index = 0;
}
if (self.d_sym) |*d_sym| {
// TODO make this logic match freeAtom. Maybe abstract the logic
// out since the same thing is desired for both.
_ = d_sym.dbg_line_fn_free_list.remove(&decl.fn_link.macho);
if (decl.fn_link.macho.prev) |prev| {
d_sym.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
prev.next = decl.fn_link.macho.next;
if (decl.fn_link.macho.next) |next| {
next.prev = prev;
} else {
d_sym.dbg_line_fn_last = prev;
}
} else if (decl.fn_link.macho.next) |next| {
d_sym.dbg_line_fn_first = next;
next.prev = null;
}
if (d_sym.dbg_line_fn_first == &decl.fn_link.macho) {
d_sym.dbg_line_fn_first = decl.fn_link.macho.next;
}
if (d_sym.dbg_line_fn_last == &decl.fn_link.macho) {
d_sym.dbg_line_fn_last = decl.fn_link.macho.prev;
}
d_sym.dwarf.freeDecl(decl);
}
}

View File

@ -13,6 +13,7 @@ const trace = @import("../../tracy.zig").trace;
const Allocator = mem.Allocator;
const Arch = std.Target.Cpu.Arch;
const Dwarf = @import("../Dwarf.zig");
const MachO = @import("../MachO.zig");
const Object = @import("Object.zig");
const StringIndexAdapter = std.hash_map.StringIndexAdapter;
@ -71,14 +72,7 @@ stab: ?Stab = null,
next: ?*Atom,
prev: ?*Atom,
/// Previous/next linked list pointers.
/// This is the linked list node for this Decl's corresponding .debug_info tag.
dbg_info_prev: ?*Atom,
dbg_info_next: ?*Atom,
/// Offset into .debug_info pointing to the tag for this Decl.
dbg_info_off: u32,
/// Size of the .debug_info tag for this Decl, not including padding.
dbg_info_len: u32,
dbg_info_atom: Dwarf.DebugInfoAtom,
dirty: bool = true,
@ -188,10 +182,7 @@ pub const empty = Atom{
.alignment = 0,
.prev = null,
.next = null,
.dbg_info_prev = null,
.dbg_info_next = null,
.dbg_info_off = undefined,
.dbg_info_len = undefined,
.dbg_info_atom = undefined,
};
pub fn deinit(self: *Atom, allocator: Allocator) void {

File diff suppressed because it is too large Load Diff