diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-10-18 23:14:23 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-10-19 21:56:47 +0200 |
| commit | 400faec10beed6c146bc562efab146be258471d7 (patch) | |
| tree | 19490d9fd5a0b66de4cb79974fc805d6c465314f /src/link | |
| parent | 4f66efdc7f2158330b73f40a44b1f16b43c5318a (diff) | |
| download | zig-400faec10beed6c146bc562efab146be258471d7.tar.gz zig-400faec10beed6c146bc562efab146be258471d7.zip | |
dwarf: introduce Dwarf.Format to be able to select 32/64bit format at whim
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Dwarf.zig | 278 | ||||
| -rw-r--r-- | src/link/Elf.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 2 |
4 files changed, 115 insertions, 169 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 93f705450a..fca8dd64a4 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1,32 +1,7 @@ -const Dwarf = @This(); - -const std = @import("std"); -const builtin = @import("builtin"); -const assert = std.debug.assert; -const fs = std.fs; -const leb128 = std.leb; -const log = std.log.scoped(.dwarf); -const mem = std.mem; - -const link = @import("../link.zig"); -const trace = @import("../tracy.zig").trace; - -const Allocator = mem.Allocator; -const DW = std.dwarf; -const File = link.File; -const LinkBlock = File.LinkBlock; -const LinkFn = File.LinkFn; -const LinkerLoad = @import("../codegen.zig").LinkerLoad; -const Module = @import("../Module.zig"); -const InternPool = @import("../InternPool.zig"); -const StringTable = @import("strtab.zig").StringTable; -const Type = @import("../type.zig").Type; -const Value = @import("../value.zig").Value; - allocator: Allocator, bin_file: *File, +format: Format, ptr_width: PtrWidth, -target: std.Target, /// A list of `Atom`s whose Line Number Programs have surplus capacity. /// This is the same concept as `Section.free_list` in Elf; see those doc comments. @@ -983,17 +958,17 @@ const min_nop_size = 2; /// actual_capacity + (actual_capacity / ideal_factor) const ideal_factor = 3; -pub fn init(allocator: Allocator, bin_file: *File, target: std.Target) Dwarf { - const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { +pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf { + const ptr_width: PtrWidth = switch (bin_file.options.target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, else => unreachable, }; - return Dwarf{ + return .{ .allocator = allocator, .bin_file = bin_file, + .format = format, .ptr_width = ptr_width, - .target = target, }; } @@ -1129,7 +1104,7 @@ pub fn commitDeclState( const decl = mod.declPtr(decl_index); const ip = &mod.intern_pool; - const target_endian = self.target.cpu.arch.endian(); + const target_endian = self.bin_file.options.target.cpu.arch.endian(); assert(decl.has_tv); switch (decl.ty.zigTypeTag(mod)) { @@ -1837,12 +1812,10 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes); defer di_buf.deinit(); - const target_endian = self.target.cpu.arch.endian(); - const init_len_size: usize = if (self.bin_file.tag == .macho) - 4 - else switch (self.ptr_width) { - .p32 => @as(usize, 4), - .p64 => 12, + const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const init_len_size: usize = switch (self.format) { + .dwarf32 => 4, + .dwarf64 => 12, }; // initial length - length of the .debug_info contribution for this compilation unit, @@ -1851,32 +1824,16 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u const after_init_len = di_buf.items.len + init_len_size; const dbg_info_end = self.getDebugInfoEnd().?; const init_len = dbg_info_end - after_init_len; - if (self.bin_file.tag == .macho) { - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len))); - } else switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(init_len)), target_endian); - }, - .p64 => { - di_buf.appendNTimesAssumeCapacity(0xff, 4); - mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), init_len, target_endian); - }, - } + + if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4); + self.writeOffsetAssumeCapacity(&di_buf, init_len); + mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // DWARF version const abbrev_offset = self.abbrev_table_offset.?; - if (self.bin_file.tag == .macho) { - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset))); - di_buf.appendAssumeCapacity(8); // address size - } else switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(abbrev_offset)), target_endian); - di_buf.appendAssumeCapacity(4); // address size - }, - .p64 => { - mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), abbrev_offset, target_endian); - di_buf.appendAssumeCapacity(8); // address size - }, - } + + self.writeOffsetAssumeCapacity(&di_buf, abbrev_offset); + di_buf.appendAssumeCapacity(self.ptrWidthBytes()); // address size + // Write the form for the compile unit, which must match the abbrev table above. const name_strp = try self.strtab.insert(self.allocator, module.root_mod.root_src_path); var compile_unit_dir_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; @@ -1885,21 +1842,13 @@ pub fn writeDbgInfoHeader(self: *Dwarf, module: *Module, low_pc: u64, high_pc: u const producer_strp = try self.strtab.insert(self.allocator, link.producer_string); di_buf.appendAssumeCapacity(@intFromEnum(AbbrevKind.compile_unit)); - 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); - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(name_strp))); - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(comp_dir_strp))); - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(producer_strp))); - } else { - self.writeAddrAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset - self.writeAddrAssumeCapacity(&di_buf, low_pc); - self.writeAddrAssumeCapacity(&di_buf, high_pc); - self.writeAddrAssumeCapacity(&di_buf, name_strp); - self.writeAddrAssumeCapacity(&di_buf, comp_dir_strp); - self.writeAddrAssumeCapacity(&di_buf, producer_strp); - } + self.writeOffsetAssumeCapacity(&di_buf, 0); // DW.AT.stmt_list, DW.FORM.sec_offset + self.writeAddrAssumeCapacity(&di_buf, low_pc); + self.writeAddrAssumeCapacity(&di_buf, high_pc); + self.writeOffsetAssumeCapacity(&di_buf, name_strp); + self.writeOffsetAssumeCapacity(&di_buf, comp_dir_strp); + self.writeOffsetAssumeCapacity(&di_buf, producer_strp); + // We are still waiting on dwarf-std.org to assign DW_LANG_Zig a number: // http://dwarfstd.org/ShowIssue.php?issue=171115.1 // Until then we say it is C99. @@ -1952,13 +1901,26 @@ fn resolveCompilationDir(module: *Module, buffer: *[std.fs.MAX_PATH_BYTES]u8) [] } fn writeAddrAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), addr: u64) void { - const target_endian = self.target.cpu.arch.endian(); + const target_endian = self.bin_file.options.target.cpu.arch.endian(); switch (self.ptr_width) { .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian), .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian), } } +fn writeOffsetAssumeCapacity(self: *Dwarf, buf: *std.ArrayList(u8), off: u64) void { + const target_endian = self.bin_file.options.target.cpu.arch.endian(); + switch (self.format) { + .dwarf32 => mem.writeInt( + u32, + buf.addManyAsArrayAssumeCapacity(4), + @as(u32, @intCast(off)), + target_endian, + ), + .dwarf64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), off, target_endian), + } +} + /// Writes to the file a buffer, prefixed and suffixed by the specified number of /// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes /// are less than 1044480 bytes (if this limit is ever reached, this function can be @@ -2174,13 +2136,7 @@ fn writeDbgInfoNopsToArrayList( } 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.bin_file.tag == .macho) - 4 - else switch (self.ptr_width) { - .p32 => @as(usize, 4), - .p64 => 12, - }; + const target_endian = self.bin_file.options.target.cpu.arch.endian(); const ptr_width_bytes = self.ptrWidthBytes(); // Enough for all the data without resizing. When support for more compilation units @@ -2191,17 +2147,15 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { // initial length - length of the .debug_aranges contribution for this compilation unit, // not including the initial length itself. // We have to come back and write it later after we know the size. + if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4); const init_len_index = di_buf.items.len; - di_buf.items.len += init_len_size; + self.writeOffsetAssumeCapacity(&di_buf, 0); const after_init_len = di_buf.items.len; 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.bin_file.tag == .macho) { - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), 0); // __debug_info offset - } else { - self.writeAddrAssumeCapacity(&di_buf, 0); // .debug_info offset - } + self.writeOffsetAssumeCapacity(&di_buf, 0); // .debug_info offset di_buf.appendAssumeCapacity(ptr_width_bytes); // address_size di_buf.appendAssumeCapacity(0); // segment_selector_size @@ -2220,18 +2174,14 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { // Go back and populate the initial length. const init_len = di_buf.items.len - after_init_len; - if (self.bin_file.tag == .macho) { - mem.writeIntLittle(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len))); - } else switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.items[init_len_index..][0..4], @as(u32, @intCast(init_len)), target_endian); - }, - .p64 => { - // initial length - length of the .debug_aranges contribution for this compilation unit, - // not including the initial length itself. - di_buf.items[init_len_index..][0..4].* = [_]u8{ 0xff, 0xff, 0xff, 0xff }; - mem.writeInt(u64, di_buf.items[init_len_index + 4 ..][0..8], init_len, target_endian); - }, + switch (self.format) { + .dwarf32 => mem.writeInt( + u32, + di_buf.items[init_len_index..][0..4], + @as(u32, @intCast(init_len)), + target_endian, + ), + .dwarf64 => mem.writeInt(u64, di_buf.items[init_len_index..][0..8], init_len, target_endian), } const needed_size = @as(u32, @intCast(di_buf.items.len)); @@ -2265,12 +2215,10 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { pub fn writeDbgLineHeader(self: *Dwarf) !void { const gpa = self.allocator; - const target_endian = self.target.cpu.arch.endian(); - const init_len_size: usize = if (self.bin_file.tag == .macho) - 4 - else switch (self.ptr_width) { - .p32 => @as(usize, 4), - .p64 => 12, + const target_endian = self.bin_file.options.target.cpu.arch.endian(); + const init_len_size: usize = switch (self.format) { + .dwarf32 => 4, + .dwarf64 => 12, }; const dbg_line_prg_off = self.getDebugLineProgramOff() orelse return; @@ -2288,20 +2236,8 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { var di_buf = try std.ArrayList(u8).initCapacity(gpa, needed_bytes); defer di_buf.deinit(); - switch (self.bin_file.tag) { - .macho => { - mem.writeIntLittle(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0)); - }, - else => switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.addManyAsArrayAssumeCapacity(4), @as(u32, 0), target_endian); - }, - .p64 => { - di_buf.appendNTimesAssumeCapacity(0xff, 4); - mem.writeInt(u64, di_buf.addManyAsArrayAssumeCapacity(8), @as(u64, 0), target_endian); - }, - }, - } + if (self.format == .dwarf64) di_buf.appendNTimesAssumeCapacity(0xff, 4); + self.writeOffsetAssumeCapacity(&di_buf, 0); mem.writeInt(u16, di_buf.addManyAsArrayAssumeCapacity(2), 4, target_endian); // version @@ -2310,16 +2246,7 @@ pub fn writeDbgLineHeader(self: *Dwarf) !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; - - // We will come back and write this. - switch (self.bin_file.tag) { - .macho => di_buf.appendNTimesAssumeCapacity(0, 4), - else => switch (self.ptr_width) { - .p32 => di_buf.appendNTimesAssumeCapacity(0, 4), - .p64 => di_buf.appendNTimesAssumeCapacity(0, 8), - }, - } - + self.writeOffsetAssumeCapacity(&di_buf, 0); // We will come back and write this. const after_header_len = di_buf.items.len; const opcode_base = DW.LNS.set_isa + 1; @@ -2372,19 +2299,14 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { di_buf.appendAssumeCapacity(0); // file names sentinel const header_len = di_buf.items.len - after_header_len; - - switch (self.bin_file.tag) { - .macho => { - mem.writeIntLittle(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len))); - }, - else => switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.items[before_header_len..][0..4], @as(u32, @intCast(header_len)), target_endian); - }, - .p64 => { - mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian); - }, - }, + switch (self.format) { + .dwarf32 => mem.writeInt( + u32, + di_buf.items[before_header_len..][0..4], + @as(u32, @intCast(header_len)), + target_endian, + ), + .dwarf64 => mem.writeInt(u64, di_buf.items[before_header_len..][0..8], header_len, target_endian), } assert(needed_bytes == di_buf.items.len); @@ -2453,17 +2375,12 @@ pub fn writeDbgLineHeader(self: *Dwarf) !void { // Backpatch actual length of the debug line program const init_len = self.getDebugLineProgramEnd().? - init_len_size; - switch (self.bin_file.tag) { - .macho => { - mem.writeIntLittle(u32, di_buf.items[0..4], @as(u32, @intCast(init_len))); + switch (self.format) { + .dwarf32 => { + mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian); }, - else => switch (self.ptr_width) { - .p32 => { - mem.writeInt(u32, di_buf.items[0..4], @as(u32, @intCast(init_len)), target_endian); - }, - .p64 => { - mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian); - }, + .dwarf64 => { + mem.writeInt(u64, di_buf.items[4..][0..8], init_len, target_endian); }, } @@ -2524,17 +2441,14 @@ fn ptrWidthBytes(self: Dwarf) u8 { } fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 { - var size = switch (self.bin_file.tag) { // length field - .macho => @sizeOf(u32), - else => switch (self.ptr_width) { - .p32 => @as(usize, @sizeOf(u32)), - .p64 => @sizeOf(u32) + @sizeOf(u64), - }, + var size: usize = switch (self.format) { // length field + .dwarf32 => @as(usize, 4), + .dwarf64 => 12, }; size += @sizeOf(u16); // version field - size += switch (self.bin_file.tag) { // offset to end-of-header - .macho => @sizeOf(u32), - else => self.ptrWidthBytes(), + size += switch (self.format) { // offset to end-of-header + .dwarf32 => @as(usize, 4), + .dwarf64 => 8, }; size += 18; // opcodes @@ -2570,6 +2484,8 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { } pub fn flushModule(self: *Dwarf, module: *Module) !void { + const target = self.bin_file.options.target; + if (self.global_abbrev_relocs.items.len > 0) { const gpa = self.allocator; var arena_alloc = std.heap.ArenaAllocator.init(gpa); @@ -2581,7 +2497,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { module, Type.anyerror, module.global_error_set.keys(), - self.target, + target, &dbg_info_buffer, ); @@ -2610,7 +2526,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void { }; var buf: [@sizeOf(u32)]u8 = undefined; - mem.writeInt(u32, &buf, self.getAtom(.di_atom, di_atom_index).off, self.target.cpu.arch.endian()); + mem.writeInt(u32, &buf, self.getAtom(.di_atom, di_atom_index).off, target.cpu.arch.endian()); while (self.global_abbrev_relocs.popOrNull()) |reloc| { const atom = self.getAtom(.di_atom, reloc.atom_index); @@ -2805,3 +2721,33 @@ fn getAtomPtr(self: *Dwarf, comptime kind: Kind, index: Atom.Index) *Atom { .di_atom => &self.di_atoms.items[index], }; } + +pub const Format = enum { + dwarf32, + dwarf64, +}; + +const Dwarf = @This(); + +const std = @import("std"); +const builtin = @import("builtin"); +const assert = std.debug.assert; +const fs = std.fs; +const leb128 = std.leb; +const log = std.log.scoped(.dwarf); +const mem = std.mem; + +const link = @import("../link.zig"); +const trace = @import("../tracy.zig").trace; + +const Allocator = mem.Allocator; +const DW = std.dwarf; +const File = link.File; +const LinkBlock = File.LinkBlock; +const LinkFn = File.LinkFn; +const LinkerLoad = @import("../codegen.zig").LinkerLoad; +const Module = @import("../Module.zig"); +const InternPool = @import("../InternPool.zig"); +const StringTable = @import("strtab.zig").StringTable; +const Type = @import("../type.zig").Type; +const Value = @import("../value.zig").Value; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 4f0312fd27..708937551a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -310,7 +310,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option if (options.module != null and !options.use_llvm) { if (!options.strip) { - self.dwarf = Dwarf.init(allocator, &self.base, options.target); + self.dwarf = Dwarf.init(allocator, &self.base, .dwarf32); } const index = @as(File.Index, @intCast(try self.files.addOne(allocator))); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 425dffd6b1..cc537cdd72 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -206,7 +206,7 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { self.d_sym = .{ .allocator = allocator, - .dwarf = link.File.Dwarf.init(allocator, &self.base, options.target), + .dwarf = link.File.Dwarf.init(allocator, &self.base, .dwarf32), .file = d_sym_file, }; } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 92e7bbe5ea..fc827b23eb 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -507,7 +507,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option } // if (!options.strip and options.module != null) { - // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, options.target); + // wasm_bin.dwarf = Dwarf.init(allocator, &wasm_bin.base, .dwarf32); // try wasm_bin.initDebugSections(); // } |
