diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-05 23:07:36 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-05 23:07:36 +0100 |
| commit | 72992b6513b3c6f5d8bd0abffe0d08a2a7d6e7cd (patch) | |
| tree | 566f64e6edf9bfe1b43e6bf397ad9bb0cc7d7795 /src | |
| parent | 908f41a67cbd377eb15d07a27778dbbca0a4309f (diff) | |
| parent | 1252bdd4d63eda5ee70b7f58979b2471c2f83555 (diff) | |
| download | zig-72992b6513b3c6f5d8bd0abffe0d08a2a7d6e7cd.tar.gz zig-72992b6513b3c6f5d8bd0abffe0d08a2a7d6e7cd.zip | |
Merge pull request #11062 from ziglang/dwarf-more-types
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 18 | ||||
| -rw-r--r-- | src/codegen.zig | 1 | ||||
| -rw-r--r-- | src/link/Elf.zig | 79 | ||||
| -rw-r--r-- | src/link/MachO.zig | 36 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 92 |
5 files changed, 158 insertions, 68 deletions
diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index f4d365dc4f..86cdf8dcdb 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -1019,7 +1019,14 @@ 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); - dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); + + // 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.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc 1, // ULEB128 dwarf expression length reg.dwarfLocOp(), @@ -1042,7 +1049,14 @@ 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); - dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter); + + // 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", .{}); + 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 diff --git a/src/codegen.zig b/src/codegen.zig index 265c205f2f..299a808447 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -639,7 +639,6 @@ pub fn generateSymbol( return Result{ .appended = {} }; }, .Optional => { - // TODO generate debug info for optionals var opt_buf: Type.Payload.ElemType = undefined; const payload_type = typed_value.ty.optionalChild(&opt_buf); const is_pl = !typed_value.val.isNull(); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1424a521b9..810bef2f9b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -983,10 +983,9 @@ pub const abbrev_subprogram_retvoid = 3; pub const abbrev_base_type = 4; pub const abbrev_ptr_type = 5; pub const abbrev_struct_type = 6; -pub const abbrev_anon_struct_type = 7; -pub const abbrev_struct_member = 8; -pub const abbrev_pad1 = 9; -pub const abbrev_parameter = 10; +pub const abbrev_struct_member = 7; +pub const abbrev_pad1 = 8; +pub const abbrev_parameter = 9; pub fn flush(self: *Elf, comp: *Compilation) !void { if (self.base.options.emit == null) { @@ -1127,13 +1126,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { DW.FORM.string, 0, 0, // table sentinel - abbrev_anon_struct_type, - DW.TAG.structure_type, - DW.CHILDREN.yes, // header - DW.AT.byte_size, - DW.FORM.sdata, - 0, - 0, // table sentinel abbrev_struct_member, DW.TAG.member, DW.CHILDREN.no, // header @@ -3186,6 +3178,7 @@ fn addDbgInfoType( dbg_info_buffer: *std.ArrayList(u8), dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable, ) error{OutOfMemory}!void { + const target = self.base.options.target; var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena); switch (ty.zigTypeTag()) { @@ -3202,7 +3195,7 @@ fn addDbgInfoType( }); }, .Int => { - const info = ty.intInfo(self.base.options.target); + const info = ty.intInfo(target); try dbg_info_buffer.ensureUnusedCapacity(12); dbg_info_buffer.appendAssumeCapacity(abbrev_base_type); // DW.AT.encoding, DW.FORM.data1 @@ -3211,7 +3204,7 @@ fn addDbgInfoType( .unsigned => DW.ATE.unsigned, }); // DW.AT.byte_size, DW.FORM.data1 - dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); + dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); }, @@ -3222,23 +3215,61 @@ fn addDbgInfoType( // DW.AT.encoding, DW.FORM.data1 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address); // DW.AT.byte_size, DW.FORM.data1 - dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(self.base.options.target))); + dbg_info_buffer.appendAssumeCapacity(@intCast(u8, ty.abiSize(target))); // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); } else { - log.debug("TODO implement .debug_info for type '{}'", .{ty}); - try dbg_info_buffer.append(abbrev_pad1); + // Non-pointer optionals are structs: struct { .maybe = *, .val = * } + var buf = try arena.create(Type.Payload.ElemType); + const payload_ty = ty.optionalChild(buf); + // DW.AT.structure_type + try dbg_info_buffer.append(abbrev_struct_type); + // DW.AT.byte_size, DW.FORM.sdata + const abi_size = ty.abiSize(target); + try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{}\x00", .{ty}); + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(7); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("maybe"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = Type.bool, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + try dbg_info_buffer.ensureUnusedCapacity(6); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.member + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("val"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + const offset = abi_size - payload_ty.abiSize(target); + try leb128.writeULEB128(dbg_info_buffer.writer(), offset); + // DW.AT.structure_type delimit children + try dbg_info_buffer.append(0); } }, .Pointer => { if (ty.isSlice()) { - // Slices are anonymous structs: struct { .ptr = *, .len = N } - try dbg_info_buffer.ensureUnusedCapacity(23); + // Slices are structs: struct { .ptr = *, .len = N } // DW.AT.structure_type - dbg_info_buffer.appendAssumeCapacity(abbrev_anon_struct_type); + try dbg_info_buffer.ensureUnusedCapacity(2); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_type); // DW.AT.byte_size, DW.FORM.sdata - dbg_info_buffer.appendAssumeCapacity(16); + dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{}\x00", .{ty}); // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(5); dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); // DW.AT.name, DW.FORM.string dbg_info_buffer.appendSliceAssumeCapacity("ptr"); @@ -3250,6 +3281,7 @@ fn addDbgInfoType( const ptr_ty = ty.slicePtrFieldType(buf); try relocs.append(.{ .ty = ptr_ty, .reloc = @intCast(u32, index) }); // DW.AT.data_member_location, DW.FORM.sdata + try dbg_info_buffer.ensureUnusedCapacity(6); dbg_info_buffer.appendAssumeCapacity(0); // DW.AT.member dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); @@ -3261,7 +3293,8 @@ fn addDbgInfoType( try dbg_info_buffer.resize(index + 4); try relocs.append(.{ .ty = Type.initTag(.usize), .reloc = @intCast(u32, index) }); // DW.AT.data_member_location, DW.FORM.sdata - dbg_info_buffer.appendAssumeCapacity(8); + try dbg_info_buffer.ensureUnusedCapacity(2); + dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize)); // DW.AT.structure_type delimit children dbg_info_buffer.appendAssumeCapacity(0); } else { @@ -3278,7 +3311,7 @@ fn addDbgInfoType( // DW.AT.structure_type try dbg_info_buffer.append(abbrev_struct_type); // DW.AT.byte_size, DW.FORM.sdata - const abi_size = ty.abiSize(self.base.options.target); + const abi_size = ty.abiSize(target); try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); // DW.AT.name, DW.FORM.string const struct_name = try ty.nameAlloc(arena); @@ -3306,7 +3339,7 @@ fn addDbgInfoType( try dbg_info_buffer.resize(index + 4); try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); // DW.AT.data_member_location, DW.FORM.sdata - const field_off = ty.structFieldOffset(field_index, self.base.options.target); + const field_off = ty.structFieldOffset(field_index, target); try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 2f55c69b3a..6bf7d183df 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -27,7 +27,6 @@ const Atom = @import("MachO/Atom.zig"); const Cache = @import("../Cache.zig"); const CodeSignature = @import("MachO/CodeSignature.zig"); const Compilation = @import("../Compilation.zig"); -const DebugSymbols = @import("MachO/DebugSymbols.zig"); const Dylib = @import("MachO/Dylib.zig"); const File = link.File; const Object = @import("MachO/Object.zig"); @@ -43,6 +42,7 @@ const TypedValue = @import("../TypedValue.zig"); const Value = @import("../value.zig").Value; pub const TextBlock = Atom; +pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); pub const base_tag: File.Tag = File.Tag.macho; @@ -2178,6 +2178,34 @@ fn writeAllAtoms(self: *MachO) !void { } } +fn writePadding(self: *MachO, match: MatchingSection, size: usize, writer: anytype) !void { + const is_code = match.seg == self.text_segment_cmd_index.? and match.sect == self.text_section_index.?; + const min_alignment: u3 = if (!is_code) + 1 + else switch (self.base.options.target.cpu.arch) { + .aarch64 => @sizeOf(u32), + .x86_64 => @as(u3, 1), + else => unreachable, + }; + + const len = @divExact(size, min_alignment); + var i: usize = 0; + while (i < len) : (i += 1) { + if (!is_code) { + try writer.writeByte(0); + } else switch (self.base.options.target.cpu.arch) { + .aarch64 => { + const inst = aarch64.Instruction.nop(); + try writer.writeIntLittle(u32, inst.toU32()); + }, + .x86_64 => { + try writer.writeByte(0x90); + }, + else => unreachable, + } + } +} + fn writeAtoms(self: *MachO) !void { var buffer = std.ArrayList(u8).init(self.base.allocator); defer buffer.deinit(); @@ -2213,11 +2241,7 @@ fn writeAtoms(self: *MachO) !void { try atom.resolveRelocs(self); try buffer.appendSlice(atom.code.items); try buffer.ensureUnusedCapacity(padding_size); - - var i: usize = 0; - while (i < padding_size) : (i += 1) { - buffer.appendAssumeCapacity(0); - } + try self.writePadding(match, padding_size, buffer.writer()); if (file_offset == null) { file_offset = sect.offset + atom_sym.n_value - sect.addr; diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index b3eb5cd5a7..f9393476dc 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -78,16 +78,15 @@ debug_aranges_section_dirty: bool = false, debug_info_header_dirty: bool = false, debug_line_header_dirty: bool = false, -const abbrev_compile_unit = 1; -const abbrev_subprogram = 2; -const abbrev_subprogram_retvoid = 3; -const abbrev_base_type = 4; -const abbrev_ptr_type = 5; -const abbrev_struct_type = 6; -const abbrev_anon_struct_type = 7; -const abbrev_struct_member = 8; -const abbrev_pad1 = 9; -const abbrev_parameter = 10; +pub const abbrev_compile_unit = 1; +pub const abbrev_subprogram = 2; +pub const abbrev_subprogram_retvoid = 3; +pub const abbrev_base_type = 4; +pub const abbrev_ptr_type = 5; +pub const abbrev_struct_type = 6; +pub const abbrev_struct_member = 7; +pub const abbrev_pad1 = 8; +pub const abbrev_parameter = 9; /// The reloc offset for the virtual address of a function in its Line Number Program. /// Size is a virtual address integer. @@ -353,13 +352,6 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti DW.FORM.string, 0, 0, // table sentinel - abbrev_anon_struct_type, - DW.TAG.structure_type, - DW.CHILDREN.yes, // header - DW.AT.byte_size, - DW.FORM.sdata, - 0, - 0, // table sentinel abbrev_struct_member, DW.TAG.member, DW.CHILDREN.no, // header @@ -1134,18 +1126,6 @@ pub fn commitDeclDebugInfo( mem.writeIntLittle(u32, ptr, @intCast(u32, text_block.size)); } - { - // Advance line and PC. - // TODO encapsulate logic in a helper function. - try dbg_line_buffer.append(DW.LNS.advance_pc); - try leb.writeULEB128(dbg_line_buffer.writer(), text_block.size); - - try dbg_line_buffer.append(DW.LNS.advance_line); - const func = decl.val.castTag(.function).?.data; - const line_off = @intCast(u28, func.rbrace_line - func.lbrace_line); - try leb.writeULEB128(dbg_line_buffer.writer(), line_off); - } - try dbg_line_buffer.appendSlice(&[_]u8{ DW.LNS.extended_op, 1, DW.LNE.end_sequence }); // Now we have the full contents and may allocate a region to store it. @@ -1332,19 +1312,57 @@ fn addDbgInfoType( // DW.AT.name, DW.FORM.string try dbg_info_buffer.writer().print("{}\x00", .{ty}); } else { - log.debug("TODO implement .debug_info for type '{}'", .{ty}); - try dbg_info_buffer.append(abbrev_pad1); + // Non-pointer optionals are structs: struct { .maybe = *, .val = * } + var buf = try arena.create(Type.Payload.ElemType); + const payload_ty = ty.optionalChild(buf); + // DW.AT.structure_type + try dbg_info_buffer.append(abbrev_struct_type); + // DW.AT.byte_size, DW.FORM.sdata + const abi_size = ty.abiSize(target); + try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{}\x00", .{ty}); + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(7); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("maybe"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = Type.bool, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + try dbg_info_buffer.ensureUnusedCapacity(6); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.member + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("val"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = payload_ty, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + const offset = abi_size - payload_ty.abiSize(target); + try leb128.writeULEB128(dbg_info_buffer.writer(), offset); + // DW.AT.structure_type delimit children + try dbg_info_buffer.append(0); } }, .Pointer => { if (ty.isSlice()) { - // Slices are anonymous structs: struct { .ptr = *, .len = N } - try dbg_info_buffer.ensureUnusedCapacity(23); + // Slices are structs: struct { .ptr = *, .len = N } // DW.AT.structure_type - dbg_info_buffer.appendAssumeCapacity(abbrev_anon_struct_type); + try dbg_info_buffer.ensureUnusedCapacity(2); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_type); // DW.AT.byte_size, DW.FORM.sdata - dbg_info_buffer.appendAssumeCapacity(16); + dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize) * 2); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{}\x00", .{ty}); // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(5); dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); // DW.AT.name, DW.FORM.string dbg_info_buffer.appendSliceAssumeCapacity("ptr"); @@ -1356,6 +1374,7 @@ fn addDbgInfoType( const ptr_ty = ty.slicePtrFieldType(buf); try relocs.append(.{ .ty = ptr_ty, .reloc = @intCast(u32, index) }); // DW.AT.data_member_location, DW.FORM.sdata + try dbg_info_buffer.ensureUnusedCapacity(6); dbg_info_buffer.appendAssumeCapacity(0); // DW.AT.member dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); @@ -1367,7 +1386,8 @@ fn addDbgInfoType( try dbg_info_buffer.resize(index + 4); try relocs.append(.{ .ty = Type.initTag(.usize), .reloc = @intCast(u32, index) }); // DW.AT.data_member_location, DW.FORM.sdata - dbg_info_buffer.appendAssumeCapacity(8); + try dbg_info_buffer.ensureUnusedCapacity(2); + dbg_info_buffer.appendAssumeCapacity(@sizeOf(usize)); // DW.AT.structure_type delimit children dbg_info_buffer.appendAssumeCapacity(0); } else { |
