authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-12 11:55:38+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-12 12:05:34+02:00
logaeaffd42f6d1c8fc92fa7669a579a8e6c46eb641
treeaad5e99e972b3cb4fe3b92aaf355ea86037de334
parentf2f1bb7cb675fc14dc7754f06329b5780091baaf

x86: fix generating debug info for variables

Add handling for these additional `MCValue`s: * `.immediate` - lower to `DW.OP.consts` or `DW.OP.constu` depending on signedness followed by popping off the DWARF stack with `DW.OP.stack_value` * `.undef` - lower to `DW.OP.implicit_value` * `.none` - lower to `DW.OP.lit0` followed by popping off the DWARF stack with `DW.OP.stack_value` For any remaining unhandled case, we generate `DW.OP.nop` in order not to mess up remaining DWARF info.

2 files changed, 54 insertions(+), 5 deletions(-)

src/arch/x86_64/CodeGen.zig+47-1
...@@ -4370,6 +4370,7 @@ fn genVarDbgInfo(...@@ -4370,6 +4370,7 @@ fn genVarDbgInfo(
4370 .dwarf => |dw| {4370 .dwarf => |dw| {
4371 const dbg_info = &dw.dbg_info;4371 const dbg_info = &dw.dbg_info;
4372 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable));4372 try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable));
4373 const endian = self.target.cpu.arch.endian();
43734374
4374 switch (mcv) {4375 switch (mcv) {
4375 .register => |reg| {4376 .register => |reg| {
...@@ -4390,7 +4391,6 @@ fn genVarDbgInfo(...@@ -4390,7 +4391,6 @@ fn genVarDbgInfo(
4390 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);4391 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
4391 },4392 },
4392 .memory, .got_load, .direct_load => {4393 .memory, .got_load, .direct_load => {
4393 const endian = self.target.cpu.arch.endian();
4394 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));4394 const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
4395 const is_ptr = switch (tag) {4395 const is_ptr = switch (tag) {
4396 .dbg_var_ptr => true,4396 .dbg_var_ptr => true,
...@@ -4425,7 +4425,53 @@ fn genVarDbgInfo(...@@ -4425,7 +4425,53 @@ fn genVarDbgInfo(
4425 else => {},4425 else => {},
4426 }4426 }
4427 },4427 },
4428 .immediate => |x| {
4429 const signedness: std.builtin.Signedness = blk: {
4430 if (ty.zigTypeTag() != .Int) break :blk .unsigned;
4431 break :blk ty.intInfo(self.target.*).signedness;
4432 };
4433 try dbg_info.ensureUnusedCapacity(2);
4434 const fixup = dbg_info.items.len;
4435 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
4436 1,
4437 switch (signedness) {
4438 .signed => DW.OP.consts,
4439 .unsigned => DW.OP.constu,
4440 },
4441 });
4442 switch (signedness) {
4443 .signed => try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)),
4444 .unsigned => try leb128.writeULEB128(dbg_info.writer(), x),
4445 }
4446 try dbg_info.append(DW.OP.stack_value);
4447 dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
4448 },
4449 .undef => {
4450 // DW.AT.location, DW.FORM.exprloc
4451 // uleb128(exprloc_len)
4452 // DW.OP.implicit_value uleb128(len_of_bytes) bytes
4453 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
4454 var implicit_value_len = std.ArrayList(u8).init(self.gpa);
4455 defer implicit_value_len.deinit();
4456 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);
4457 const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size;
4458 try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len);
4459 try dbg_info.ensureUnusedCapacity(total_exprloc_len);
4460 dbg_info.appendAssumeCapacity(DW.OP.implicit_value);
4461 dbg_info.appendSliceAssumeCapacity(implicit_value_len.items);
4462 dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size);
4463 },
4464 .none => {
4465 try dbg_info.ensureUnusedCapacity(3);
4466 dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc
4467 2, DW.OP.lit0, DW.OP.stack_value,
4468 });
4469 },
4428 else => {4470 else => {
4471 try dbg_info.ensureUnusedCapacity(2);
4472 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
4473 1, DW.OP.nop,
4474 });
4429 log.debug("TODO generate debug info for {}", .{mcv});4475 log.debug("TODO generate debug info for {}", .{mcv});
4430 },4476 },
4431 }4477 }
src/link/Dwarf.zig+7-4
...@@ -102,7 +102,7 @@ pub const DeclState = struct {...@@ -102,7 +102,7 @@ pub const DeclState = struct {
102 }102 }
103103
104 pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void {104 pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void {
105 log.debug("{x}: target sym @{d}, via GOT {}", .{ offset, target, is_ptr });105 log.debug("{x}: target sym %{d}, via GOT {}", .{ offset, target, is_ptr });
106 try self.exprloc_relocs.append(self.gpa, .{106 try self.exprloc_relocs.append(self.gpa, .{
107 .@"type" = if (is_ptr) .got_load else .direct_load,107 .@"type" = if (is_ptr) .got_load else .direct_load,
108 .target = target,108 .target = target,
...@@ -135,7 +135,7 @@ pub const DeclState = struct {...@@ -135,7 +135,7 @@ pub const DeclState = struct {
135 .@"type" = ty,135 .@"type" = ty,
136 .offset = undefined,136 .offset = undefined,
137 });137 });
138 log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });138 log.debug("%{d}: {}", .{ sym_index, ty.fmtDebug() });
139 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{139 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{
140 .mod = self.mod,140 .mod = self.mod,
141 });141 });
...@@ -143,7 +143,7 @@ pub const DeclState = struct {...@@ -143,7 +143,7 @@ pub const DeclState = struct {
143 .mod = self.mod,143 .mod = self.mod,
144 }).?;144 }).?;
145 };145 };
146 log.debug("{x}: @{d} + 0", .{ offset, resolv });146 log.debug("{x}: %{d} + 0", .{ offset, resolv });
147 try self.abbrev_relocs.append(self.gpa, .{147 try self.abbrev_relocs.append(self.gpa, .{
148 .target = resolv,148 .target = resolv,
149 .atom = atom,149 .atom = atom,
...@@ -1056,6 +1056,7 @@ pub fn commitDeclState(...@@ -1056,6 +1056,7 @@ pub fn commitDeclState(
1056 break :blk false;1056 break :blk false;
1057 };1057 };
1058 if (deferred) {1058 if (deferred) {
1059 log.debug("resolving %{d} deferred until flush", .{target});
1059 try self.global_abbrev_relocs.append(gpa, .{1060 try self.global_abbrev_relocs.append(gpa, .{
1060 .target = null,1061 .target = null,
1061 .offset = reloc.offset,1062 .offset = reloc.offset,
...@@ -1063,10 +1064,12 @@ pub fn commitDeclState(...@@ -1063,10 +1064,12 @@ pub fn commitDeclState(
1063 .addend = reloc.addend,1064 .addend = reloc.addend,
1064 });1065 });
1065 } else {1066 } else {
1067 const value = symbol.atom.off + symbol.offset + reloc.addend;
1068 log.debug("{x}: [() => {x}] (%{d}, '{}')", .{ reloc.offset, value, target, ty.fmtDebug() });
1066 mem.writeInt(1069 mem.writeInt(
1067 u32,1070 u32,
1068 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],1071 dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
1069 symbol.atom.off + symbol.offset + reloc.addend,1072 value,
1070 target_endian,1073 target_endian,
1071 );1074 );
1072 }1075 }